IDAPython for IDA 7.6

This commit is contained in:
Arnaud Diederen
2021-03-30 08:54:44 +02:00
parent 7eea22820f
commit c22e071853
106 changed files with 30280 additions and 2638 deletions
+9 -7
View File
@@ -7,9 +7,9 @@ to the C++ SDK which will then be reflected in IDAPython, an *immensely*
useful rule-of-thumb is to perform a diff of the autogenerated SWiG wrappers.
Typically:
`cp -R obj/x64_linux_gcc_32/wrappers/ /tmp/wrappers-before`
`cp -R obj/x64_linux_gcc_32/3/wrappers/ /tmp/wrappers-before`
<recompile...>
`git diff /tmp/wrappers-before/ obj/x64_linux_gcc_32/wrappers/`
`git diff /tmp/wrappers-before/ obj/x64_linux_gcc_32/3/wrappers/`
It is always useful to make sure that SWiG did the right thing -- *especially*
when modifying typemaps, but not only.
@@ -28,17 +28,19 @@ We use the "zzz" placeholder for a module name in this "how-to".
2. add zzz to the `MODULES_NAMES` var in makefile
3. add a line to python/idc.py if you want to autoload this module
3. add zzz to `SDK_FILES` var in etc/sdk/sdk_files.mak
4. add a line to python/idc.py if you want to autoload this module
```
import ida_zzz
```
4. build
5. build
5. update the content of api_contents.txt
6. update the content of api_contents.txt
(from obj/.../api_contents.txt.new)
6. rebuild
7. rebuild
7. update the content of pydoc_injections.txt
8. update the content of pydoc_injections.txt
(from obj/.../pydoc_injections.txt)
+1 -1
View File
@@ -4,7 +4,7 @@ A script that tries to determine the call stack
Run the application with the debugger, suspend the debugger, select a thread and finally run the script.
Copyright (c) 1990-2020 Hex-Rays
Copyright (c) 1990-2021 Hex-Rays
ALL RIGHTS RESERVED.
"""
import ida_ua
+1 -1
View File
@@ -2,7 +2,7 @@
A script to demonstrate how to send commands to the debugger and then parse and use the output in IDA
Copyright (c) 1990-2020 Hex-Rays
Copyright (c) 1990-2021 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -2,7 +2,7 @@
This script shows how to send debugger commands and use the result in IDA
Copyright (c) 1990-2020 Hex-Rays
Copyright (c) 1990-2021 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -13,7 +13,7 @@ The general syntax is:
* To specify in which context the instructions should be assembled, pass asm_where=ea:
find("jmp dword ptr [esp]", asm_where=here())
Copyright (c) 1990-2020 Hex-Rays
Copyright (c) 1990-2021 Hex-Rays
ALL RIGHTS RESERVED.
"""
from __future__ import print_function
+1 -1
View File
@@ -4,7 +4,7 @@ A script that graphs all the exception handlers in a given process
It will be easy to see what thread uses what handler and what handlers are commonly used between threads
Copyright (c) 1990-2020 Hex-Rays
Copyright (c) 1990-2021 Hex-Rays
ALL RIGHTS RESERVED.
"""
from __future__ import print_function
+1 -1
View File
@@ -2,7 +2,7 @@
This script shows how to send debugger commands and use the result in IDA
Copyright (c) 1990-2020 Hex-Rays
Copyright (c) 1990-2021 Hex-Rays
ALL RIGHTS RESERVED.
"""
+1 -1
View File
@@ -2,7 +2,7 @@ from __future__ import print_function
# -----------------------------------------------------------------------
# VirusTotal IDA Plugin
# By Elias Bachaalany <elias at hex-rays.com>
# (c) Hex-Rays 2011-2020
# (c) Hex-Rays 2011-2021
#
# Special thanks:
# - VirusTotal team
+488 -124
View File
File diff suppressed because it is too large Load Diff
+434 -82
View File
File diff suppressed because it is too large Load Diff
+4
View File
@@ -9,6 +9,10 @@ class SayHi(ida_kernwin.action_handler_t):
def activate(self, ctx):
print("Hi, %s" % (self.message))
# print("context fields: %s" % dir(ctx))
print(" cur_ea %08X" % ctx.cur_ea)
print(" cur_value: %08X" % ctx.cur_value)
print(" cur_extracted_ea %08X" % ctx.cur_extracted_ea)
return 1
# You can implement update(), to inform IDA when:
+89
View File
@@ -0,0 +1,89 @@
from __future__ import print_function
# IDAPython's ida_bytes.bin_search function is pretty powerful,
# but can be tough to figure out at first. This example introduces
# * ida_bytes.bin_search, and
# * ida_bytes.parse_binpat_str
# in order to implement a simple replacement for the
# 'Search > Sequence of bytes...' dialog, that lets users
# search for sequences of bytes that compose string literals
# in the binary file (either in the default 1-byte-per-char
# encoding, or as UTF-16.)
import ida_kernwin
import ida_bytes
import ida_ida
import ida_idaapi
import ida_nalt
class search_strlit_form_t(ida_kernwin.Form):
def __init__(self):
ida_kernwin.Form.__init__(
self,
r"""Please enter string literal
<Text: {Text}>
<#UTF16-BE if file is big-endian, UTF16-LE otherwise#As UTF-16: {UTF16}>{Encoding}>
""",
{
"Text" : ida_kernwin.Form.StringInput(),
"Encoding" : ida_kernwin.Form.ChkGroupControl(("UTF16",)),
})
class search_strlit_ah_t(ida_kernwin.action_handler_t):
def __init__(self):
ida_kernwin.action_handler_t.__init__(self)
def activate(self, ctx):
f = search_strlit_form_t()
f, args = f.Compile()
ok = f.Execute()
if ok:
current_ea = ida_kernwin.get_screen_ea()
patterns = ida_bytes.compiled_binpat_vec_t()
encoding = ida_nalt.get_default_encoding_idx(
ida_nalt.BPU_2B if f.Encoding.value else ida_nalt.BPU_1B)
# string literals must be quoted. That's how parse_binpat_str
# recognizes them (we want to be careful though: the user
# might type in something like 'L"hello"', which should
# decode to the IDB-specific wide-char set of bytes)
text = f.Text.value
if text.find('"') < 0:
text = '"%s"' % text
err = ida_bytes.parse_binpat_str(
patterns,
current_ea,
text,
10, # radix (not that it matters though, since we're all about string literals)
encoding)
if not err:
ea = ida_bytes.bin_search(
current_ea,
ida_ida.inf_get_max_ea(),
patterns,
ida_bytes.BIN_SEARCH_FORWARD
| ida_bytes.BIN_SEARCH_NOBREAK
| ida_bytes.BIN_SEARCH_NOSHOW)
ok = ea != ida_idaapi.BADADDR
if ok:
ida_kernwin.jumpto(ea)
else:
print("Failed parsing binary pattern: \"%s\"" % err)
return ok
def update(self, ctx):
return ida_kernwin.AST_ENABLE_FOR_WIDGET \
if ctx.widget_type == ida_kernwin.BWN_DISASM \
else ida_kernwin.AST_DISABLE_FOR_WIDGET
ACTION_NAME = "bin_search:search"
ACTION_SHORTCUT = "Ctrl+Shift+S"
if ida_kernwin.register_action(
ida_kernwin.action_desc_t(
ACTION_NAME,
"Search for string literal",
search_strlit_ah_t(),
ACTION_SHORTCUT)):
print("Please use \"%s\" to search for string literals" % ACTION_SHORTCUT)
+12 -3
View File
@@ -1,8 +1,17 @@
"""
summary: change background colours
description:
This illustrates the setting/retrieval of background colours
using the IDC wrappers
category: disassembly
keywords: coloring, idc
"""
from __future__ import print_function
#---------------------------------------------------------------------
# This illustrates the setting/retrievel of background colours,
# using the IDC wrappers
BG_BLUE = 0xc02020
BG_GREEN = 0x208020
+66
View File
@@ -0,0 +1,66 @@
from __future__ import print_function
# This example illustrates how to accurately retrieve the current selection.
#
# After running this script:
# * select some text in one of the listing widgets (i.e.,
# "IDA View-*", "Enums", "Structures", "Pseudocode-*")
# * press Ctrl+Shift+S to dump the selection
#
# (c) Hex-Rays
import ida_kernwin
import ida_lines
class dump_selection_handler_t(ida_kernwin.action_handler_t):
def activate(self, ctx):
if ctx.has_flag(ida_kernwin.ACF_HAS_SELECTION):
tp0, tp1 = ctx.cur_sel._from, ctx.cur_sel.to
ud = ida_kernwin.get_viewer_user_data(ctx.widget)
lnar = ida_kernwin.linearray_t(ud)
lnar.set_place(tp0.at)
lines = []
while True:
cur_place = lnar.get_place()
first_line_ref = ida_kernwin.l_compare2(cur_place, tp0.at, ud)
last_line_ref = ida_kernwin.l_compare2(cur_place, tp1.at, ud)
if last_line_ref > 0: # beyond last line
break
line = ida_lines.tag_remove(lnar.down())
if last_line_ref == 0: # at last line
line = line[0:tp1.x]
elif first_line_ref == 0: # at first line
line = ' ' * tp0.x + line[tp0.x:]
lines.append(line)
for line in lines:
print(line)
return 1
def update(self, ctx):
ok_widgets = [
ida_kernwin.BWN_DISASM,
ida_kernwin.BWN_STRUCTS,
ida_kernwin.BWN_ENUMS,
ida_kernwin.BWN_PSEUDOCODE,
]
return ida_kernwin.AST_ENABLE_FOR_WIDGET \
if ctx.widget_type in ok_widgets \
else ida_kernwin.AST_DISABLE_FOR_WIDGET
# -----------------------------------------------------------------------
# create actions (and attach them to IDA View-A's context menu if possible)
ACTION_NAME = "dump_selection"
ACTION_SHORTCUT = "Ctrl+Shift+S"
if ida_kernwin.unregister_action(ACTION_NAME):
print("Unregistered previously-registered action \"%s\"" % ACTION_NAME)
if ida_kernwin.register_action(
ida_kernwin.action_desc_t(
ACTION_NAME,
"Dump selection",
dump_selection_handler_t(),
ACTION_SHORTCUT)):
print("Registered action \"%s\"" % ACTION_NAME)
@@ -0,0 +1,96 @@
"""
This example shows how one can dynamically alter the lines background
rendering for pseudocode listings (as opposed to using
ida_hexrays.cfunc_t.pseudocode[N].bgcolor)
After running this script, pressing 'M' on a line in a "Pseudocode-?"
widget, will cause that line to be rendered with a special background color.
"""
import ida_kernwin
import ida_hexrays
import ida_moves
import ida_idaapi
class pseudo_line_t(object):
def __init__(self, func_ea, line_nr):
self.func_ea = func_ea
self.line_nr = line_nr
def __hash__(self):
return hash((self.func_ea, self.line_nr))
def __eq__(self, r):
return self.func_ea == r.func_ea \
and self.line_nr == r.line_nr
def _place_to_line_number(p):
return ida_kernwin.place_t.as_simpleline_place_t(p).n
class pseudocode_lines_rendering_hooks_t(ida_kernwin.UI_Hooks):
def __init__(self):
ida_kernwin.UI_Hooks.__init__(self)
self.marked_lines = {}
def get_lines_rendering_info(self, out, widget, rin):
vu = ida_hexrays.get_widget_vdui(widget)
if vu:
entry_ea = vu.cfunc.entry_ea
for section_lines in rin.sections_lines:
for line in section_lines:
coord = pseudo_line_t(
entry_ea,
_place_to_line_number(line.at))
color = self.marked_lines.get(coord, None)
if color is not None:
e = ida_kernwin.line_rendering_output_entry_t(line)
e.bg_color = color
out.entries.push_back(e)
class toggle_line_marked_ah_t(ida_kernwin.action_handler_t):
"""
We could very well use an ARGB value, but instead let's go
go with a color 'key': those can be altered by the user/theme,
and therefore have a better chance of being appropriate (or at
least expected.)
"""
COLOR_KEY = ida_kernwin.CK_EXTRA11
def __init__(self, hooks):
ida_kernwin.action_handler_t.__init__(self)
self.hooks = hooks
def activate(self, ctx):
vu = ida_hexrays.get_widget_vdui(ctx.widget)
if vu:
loc = ida_moves.lochist_entry_t()
if ida_kernwin.get_custom_viewer_location(loc, ctx.widget):
coord = pseudo_line_t(
vu.cfunc.entry_ea,
_place_to_line_number(loc.place()))
if coord in self.hooks.marked_lines.keys():
del self.hooks.marked_lines[coord]
else:
self.hooks.marked_lines[coord] = self.COLOR_KEY
ida_kernwin.refresh_custom_viewer(ctx.widget)
def update(self, ctx):
return ida_kernwin.AST_ENABLE_FOR_WIDGET \
if ctx.widget_type == ida_kernwin.BWN_PSEUDOCODE \
else ida_kernwin.AST_DISABLE_FOR_WIDGET
hooks = pseudocode_lines_rendering_hooks_t()
act_name = "example:colorize_pseudocode_line"
act_shortcut = "M"
if ida_kernwin.register_action(ida_kernwin.action_desc_t(
act_name,
"Mark pseudocode line",
toggle_line_marked_ah_t(hooks),
act_shortcut)):
hooks.hook()
print("Action registered. Please press '%s' in a pseudocode window to mark a line" % act_shortcut)
+56 -22
View File
@@ -1,10 +1,12 @@
from __future__ import print_function
#
# This example tries to load a decompiler plugin corresponding to the current
# architecture (and address size) right after auto-analysis is performed,
# and then tries to decompile the function at the first entrypoint.
#
# It is particularly suited for use with the '-S' flag.
# It is particularly suited for use with the '-S' flag, for example:
# idat -Ldecompile.log -Sdecompile_entry_points.py -c file
#
import ida_ida
@@ -13,30 +15,62 @@ import ida_loader
import ida_hexrays
import ida_idp
import ida_entry
import ida_kernwin
ida_auto.auto_wait()
ALL_DECOMPILERS = {
ida_idp.PLFM_386 : ("hexrays", "hexx64"),
ida_idp.PLFM_ARM : ("hexarm", "hexarm64"),
ida_idp.PLFM_PPC : ("hexppc", "hexppc64"),
ida_idp.PLFM_MIPS: ("hexmips", "hexmips64"),
}
pair = ALL_DECOMPILERS.get(ida_idp.ph.id, None)
if pair:
decompiler = pair[1 if ida_ida.cvar.inf.is_64bit() else 0]
# because the -S script runs very early, we need to load the decompiler
# manually if we want to use it
def init_hexrays():
ALL_DECOMPILERS = {
ida_idp.PLFM_386: "hexrays",
ida_idp.PLFM_ARM: "hexarm",
ida_idp.PLFM_PPC: "hexppc",
ida_idp.PLFM_MIPS: "hexmips",
}
cpu = ida_idp.ph.id
decompiler = ALL_DECOMPILERS.get(cpu, None)
if not decompiler:
print("No known decompilers for architecture with ID: %d" % ida_idp.ph.id)
return False
if ida_ida.inf_is_64bit():
if cpu == ida_idp.PLFM_386:
decompiler = "hexx64"
else:
decompiler += "64"
if ida_loader.load_plugin(decompiler) and ida_hexrays.init_hexrays_plugin():
return True
else:
print('Couldn\'t load or initialize decompiler: "%s"' % decompiler)
return False
def decompile_func(ea, outfile):
ida_kernwin.msg("Decompiling at: %X..." % ea)
cf = ida_hexrays.decompile(ea)
if cf:
ida_kernwin.msg("OK\n")
outfile.write(str(cf) + "\n")
else:
ida_kernwin.msg("failed!\n")
outfile.write("decompilation failure at %X!\n" % ea)
def main():
print("Waiting for autoanalysis...")
ida_auto.auto_wait()
if init_hexrays():
eqty = ida_entry.get_entry_qty()
if eqty:
ea = ida_entry.get_entry(ida_entry.get_entry_ordinal(0))
print("Decompiling at: %X" % ea)
cf = ida_hexrays.decompile(ea)
if cf:
print(cf)
else:
print("Decompilation failed")
idbpath = idc.get_idb_path()
cpath = idbpath[:-4] + ".c"
with open(cpath, "w") as outfile:
print("writing results to '%s'..." % cpath)
for i in range(eqty):
ea = ida_entry.get_entry(ida_entry.get_entry_ordinal(i))
decompile_func(ea, outfile)
else:
print("No known entrypoint. Cannot decompile.")
else:
print("Couldn't load or initialize decompiler: \"%s\"" % decompiler)
else:
print("No known decompilers for architecture with ID: %d" % ida_idp.ph.id)
if ida_kernwin.cvar.batch:
print("All done, exiting.")
ida_pro.qexit(0)
main()
+1 -1
View File
@@ -1,6 +1,6 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2021 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
+1 -1
View File
@@ -1,6 +1,6 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2021 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
+1 -1
View File
@@ -1,6 +1,6 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2021 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample script for Hex-Rays Decompiler.
+1 -1
View File
@@ -1,6 +1,6 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2021 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample script for Hex-Rays Decompiler.
+1 -1
View File
@@ -1,6 +1,6 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2021 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
+1 -1
View File
@@ -1,6 +1,6 @@
#
# Hex-Rays Decompiler project
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2021 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample plugin for Hex-Rays Decompiler.
+85
View File
@@ -0,0 +1,85 @@
""" Example: provide custom call type dynamically
This plugin can greatly improve decompilation of indirect calls:
call [eax+4]
For them, the decompiler has to guess the prototype of the called function.
This has to be done at a very early phase of decompilation because
the function prototype influences the data flow analysis. On the other
hand, we do not have global data flow analysis results yet because
we haven't analyzed all calls in the function. It is a chicked-and-egg
problem.
The decompiler uses various techniques to guess the called function
prototype. While it works very well, it may fail in some cases.
To fix, the user can specify the call prototype manually, using
"Edit, Operand types, Set operand type" at the call instruction.
This plugin illustrates another approach to the problem:
if you happen to be able to calculate the call prototypes dynamically,
this is how to inform the decompiler about them.
"""
import ida_idaapi
import ida_nalt
import ida_kernwin
import ida_typeinf
import ida_hexrays
class callinfo_provider_t(ida_hexrays.Hexrays_Hooks):
# this callback will be called for all call instructions
# our plugin may provide the function prototype or even a complete new callinfo
# object. The callinfo object may be useful if the prototype is not enough
# to express all details of the call.
def build_callinfo(self, blk, type, callinfo):
# it is a good idea to skip direct calls.
# note that some indirect calls may be resolved and become direct calls,
# and will be filtered out here:
ida_kernwin.msg("%x: got called for: %s\n" % (blk.tail.ea, blk.tail.dstr()))
tail = blk.tail
if tail.opcode == ida_hexrays.m_call:
return 0
# also, if the type was specified by the user, do not interfere
call_ea = tail.ea
tif = ida_typeinf.tinfo_t()
if ida_nalt.get_op_tinfo(tif, call_ea, 0):
return 0
# ok, the decompiler really has to guess the type.
# just for the sake of an example, return a predefined prototype.
# in real life you will provide the prototype you discovered yourself,
# using your magic of yours :)
my_proto = "int f();"
ida_kernwin.msg("%x: providing prototype %s\n" % (call_ea, my_proto))
ida_typeinf.parse_decl(type, None, my_proto, 0)
return 0
# a plugin interface, boilerplate code
class my_plugin_t(ida_idaapi.plugin_t):
flags = ida_idaapi.PLUGIN_HIDE
wanted_name = "Hex-Rays custom prototype provider (IDAPython)"
wanted_hotkey = ""
comment = "Sample plugin21 for Hex-Rays decompiler"
help = ""
def init(self):
if ida_hexrays.init_hexrays_plugin():
self.hooks = callinfo_provider_t()
self.hooks.hook()
ida_kernwin.warning(
"Installed callinfo provider sample (vds21.py)\n" +\
"Please note that it is just an example\n" +\
"and will spoil your decompilations!")
return ida_idaapi.PLUGIN_KEEP # keep us in the memory
def term(self):
self.hooks.unhook()
def run(self, arg):
pass
def PLUGIN_ENTRY():
return my_plugin_t()
+2 -2
View File
@@ -56,7 +56,7 @@ class hexrays_callback_info(object):
try:
data = self.node.getblob(0, 'I')
if data:
self.stored = eval(data)
self.stored = eval(data.decode("UTF-8"))
print('Invert-if: Loaded %s' % (repr(self.stored), ))
except:
print('Failed to load invert-if locations')
@@ -68,7 +68,7 @@ class hexrays_callback_info(object):
def save(self):
try:
self.node.setblob(repr(self.stored), 0, 'I')
self.node.setblob(repr(self.stored).encode("UTF-8"), 0, 'I')
except:
print('Failed to save invert-if locations')
traceback.print_exc()
+1 -1
View File
@@ -1,6 +1,6 @@
# Hex-Rays Decompiler project
# Copyright (c) 2007-2020 by Hex-Rays, support@hex-rays.com
# Copyright (c) 2007-2021 by Hex-Rays, support@hex-rays.com
# ALL RIGHTS RESERVED.
#
# Sample script for Hex-Rays Decompiler usage of udc_filter_t
+15 -12
View File
@@ -1,17 +1,20 @@
"""
This is a sample script, that will record (in memory) all changes in
functions prototypes, in order to re-apply them later.
summary: Record and replay changes in function prototypes
To use this script:
- open an IDB (say, "test.idb")
- modify some functions prototypes (e.g., by triggering the 'Y'
shortcut when the cursor is placed on the first address of a
function)
- reload that IDB, *without saving it first*
- call rpc.replay(), to re-apply the modifications.
Note: 'ti_changed' is also called for changes to the function
frames, but we'll only record function prototypes changes.
description:
This is a sample script, that will record (in memory) all changes in
functions prototypes, in order to re-apply them later.
.
To use this script:
- open an IDB (say, "test.idb")
- modify some functions prototypes (e.g., by triggering the 'Y'
shortcut when the cursor is placed on the first address of a
function)
- reload that IDB, *without saving it first*
- call rpc.replay(), to re-apply the modifications.
.
Note: 'ti_changed' is also called for changes to the function
frames, but we'll only record function prototypes changes.
"""
import ida_idp
import ida_funcs
+4728
View File
File diff suppressed because it is too large Load Diff
+2870
View File
File diff suppressed because it is too large Load Diff
+4 -4
View File
@@ -1,6 +1,6 @@
#
# This example illustrates how one can execute commands in the
# "Output window", from their own widgets.
# "Output" window, from their own widgets.
#
# In order to do so, we have to be careful that:
# - the original, underlying 'cli:Execute' action, that has to be
@@ -54,13 +54,13 @@ def show_dialog():
# We'll now have to schedule a call to the standard
# 'execute' action. We can't call it right away, because
# the "Output window" doesn't have focus, and thus
# the "Output" window doesn't have focus, and thus
# the action will fail to execute since it requires
# the "Output window" as context.
# the "Output" window as context.
text = text_edit.toPlainText()
def delayed_exec(*args):
output_window_title = "Output window"
output_window_title = "Output"
tw = ida_kernwin.find_widget(output_window_title)
if not tw:
raise Exception("Couldn't find widget '%s'" % output_window_title)
+28
View File
@@ -0,0 +1,28 @@
"""
We color the function in the Function window according to its size.
The larger the function, the darker the color.
"""
import ida_kernwin
import ida_funcs
import math
class func_chooser_coloring_hooks_t(ida_kernwin.UI_Hooks):
def __init__(self):
ida_kernwin.UI_Hooks.__init__(self)
self.colors = [0x808080 + (32-i) * 0x400 for i in range(32-5)]
def get_chooser_item_attrs(self, chobj, n, attrs):
if attrs.color != 0xFFFFFFFF:
return # the color is already set
ea = chobj.get_ea(n)
fn = ida_funcs.get_func(ea)
size = fn.size()
if size < 32:
return # do not color small functions
attrs.color = self.colors[int(math.log2(size))]
fcch = func_chooser_coloring_hooks_t()
fcch.hook()
ida_kernwin.enable_chooser_item_attrs("Functions", True)
+14 -3
View File
@@ -1,9 +1,20 @@
"""
summary: manipulate IDAView and graph
description:
This is an example illustrating how to manipulate an existing IDA-provided
view (and thus its graph), in Python.
keywords: idaview, graph
see_also: custom_graph_with_actions, sync_two_graphs
"""
from __future__ import print_function
# -----------------------------------------------------------------------
# This is an example illustrating how to manipulate an existing IDA-provided
# view (and thus its graph), in Python.
# (c) Hex-Rays
#
from time import sleep
import threading
@@ -0,0 +1,112 @@
"""
summary:
This example illustrates how one can implement a "jump to next comment"
action within IDA's disassembly view.
description:
We want our action not only to find the next line containing a comment,
but to also place the cursor at the right horizontal position.
To find that position, we will have to inspect the text that IDA
generates, looking for the start of a comment.
However, we won't be looking for a comment "prefix" (e.g., "; "),
as that would be too fragile.
Instead, we will look for special "tags" that IDA injects into textual
lines, and that bear semantic information.
Those tags are primarily used for rendering (i.e., switching colors),
but can also be very handy for spotting tokens of interest (registers,
addresses, comments, prefixes, instruction mnemonics, ...)
see_also: save_and_restore_listing_pos
"""
import ida_idaapi
import ida_kernwin
import ida_bytes
import ida_moves
import ida_lines
def find_comment_visual_position_in_tagged_line(line):
"""
We'll look for tags for all types of comments, and if
found return the visual position of the tag in the line
(using 'ida_lines.tag_strlen')
"""
for cmt_type in [
ida_lines.SCOLOR_REGCMT,
ida_lines.SCOLOR_RPTCMT,
ida_lines.SCOLOR_AUTOCMT]:
cmt_idx = line.find(ida_lines.SCOLOR_ON + cmt_type)
if cmt_idx > -1:
return ida_lines.tag_strlen(line[:cmt_idx])
return -1
def jump_next_comment(v):
"""
Starting at the current line, keep generating lines until
a comment is found. When this happens, position the viewer
at the right coordinates.
"""
loc = ida_moves.lochist_entry_t()
if ida_kernwin.get_custom_viewer_location(loc, v):
place = loc.place()
idaplace = ida_kernwin.place_t_as_idaplace_t(place)
ea = idaplace.ea
while ea != ida_idaapi.BADADDR:
_, disass = ida_lines.generate_disassembly(
ea,
1000, # maximum number of lines
False, # as_stack=False
False) # notags=False - we want tags, in order to spot comments
found = None
# If this is the start item, start at the next line
start_lnnum = (idaplace.lnnum + 1) if ea == idaplace.ea else 0
for rel_lnnum, line in enumerate(disass[start_lnnum:]):
vis_cx = find_comment_visual_position_in_tagged_line(line)
if vis_cx > -1:
found = (ea, rel_lnnum, vis_cx)
break
if found is not None:
idaplace.ea = found[0]
idaplace.lnnum = start_lnnum + found[1]
loc.set_place(idaplace)
loc.renderer_info().pos.cx = found[2]
ida_kernwin.custom_viewer_jump(v, loc, ida_kernwin.CVNF_LAZY)
break
ea = ida_bytes.next_head(ea, ida_idaapi.BADADDR)
class jump_next_comment_ah_t(ida_kernwin.action_handler_t):
def activate(self, ctx):
jump_next_comment(ctx.widget)
def update(self, ctx):
return ida_kernwin.AST_ENABLE_FOR_WIDGET \
if ctx.widget_type == ida_kernwin.BWN_DISASM \
else ida_kernwin.AST_DISABLE_FOR_WIDGET
ACTION_NAME = "jump_next_comment:jump"
ACTION_LABEL = "Jump to the next comment"
ACTION_SHORTCUT = "Ctrl+Alt+C"
ACTION_HELP = "Press %s to jump to the next comment" % ACTION_SHORTCUT
if ida_kernwin.unregister_action(ACTION_NAME):
print("Unregistered previously-registered action \"%s\"" % ACTION_LABEL)
if ida_kernwin.register_action(
ida_kernwin.action_desc_t(
ACTION_NAME,
ACTION_LABEL,
jump_next_comment_ah_t(),
ACTION_SHORTCUT)):
print("Registered action \"%s\". %s" % (ACTION_LABEL, ACTION_HELP))
+51
View File
@@ -0,0 +1,51 @@
# -----------------------------------------------------------------------
# This is an example illustrating how to add custom menus to IDA, either
# at the toplevel (i.e., the menubar), or as submenus in existing menus.
# (c) Hex-Rays
#
import ida_kernwin
# Create custom menus
ida_kernwin.create_menu("MyToplevelMenu", "&Custom menu", "View")
ida_kernwin.create_menu("MySubMenu", "Custom s&ubmenu", "View/Print internal flags")
# Create some actions
class greeter_t(ida_kernwin.action_handler_t):
def __init__(self, greetings):
ida_kernwin.action_handler_t.__init__(self)
self.greetings = greetings
def activate(self, ctx):
print(self.greetings)
def update(self, ctx):
return ida_kernwin.AST_ENABLE_ALWAYS
ACTION_NAME_0 = "my_action_0"
ACTION_NAME_1 = "my_action_1"
for action_name, greetings in [
(ACTION_NAME_0, "Hello, world"),
(ACTION_NAME_1, "Hi there"),
]:
desc = ida_kernwin.action_desc_t(
action_name, "Say \"%s\"" % greetings, greeter_t(greetings))
if ida_kernwin.register_action(desc):
print("Registered action \"%s\"" % action_name)
# Then, let's attach some actions to them - both core actions
# and custom ones is allowed (also, any action can be attached
# to multiple menus.)
for action_name, path in [
(ACTION_NAME_0, "Custom menu"),
(ACTION_NAME_0, "View/Custom submenu/"),
(ACTION_NAME_1, "Custom menu"),
(ACTION_NAME_1, "View/Custom submenu/"),
("About", "Custom menu"),
("About", "View/Custom submenu/"),
]:
ida_kernwin.attach_action_to_menu(
path,
action_name,
ida_kernwin.SETMENU_INS)
@@ -1,3 +1,7 @@
"""
summary: choose multi
"""
from __future__ import print_function
from ida_kernwin import Choose
@@ -0,0 +1,253 @@
import inspect
import ida_kernwin
import ida_dirtree
import ida_netnode
class my_dirspec_t(ida_dirtree.dirspec_t):
def __init__(self, chooser):
ida_dirtree.dirspec_t.__init__(self)
self.chooser = chooser
def log_frame(self):
if self.chooser.dirspec_log:
stack = inspect.stack()
frame, _, _, _, _, _ = stack[1]
args, _, _, values = inspect.getargvalues(frame)
print(">>> %s: args=%s" % (inspect.getframeinfo(frame)[2], [(i, values[i]) for i in args[1:]]))
def get_name(self, inode):
self.log_frame()
def find_inode(index, ordinal, _inode):
if inode == _inode:
return "inode #%d" % inode
return self.chooser._for_each_item(find_inode)
def get_inode(self, diridx, name):
self.log_frame()
if not name.startswith("inode #"):
return ida_dirtree.direntry_t.BADIDX
return int(name[7:])
def get_size(self, inode):
self.log_frame()
return 1
def get_attrs(self, inode):
self.log_frame()
def rename_inode(self, inode, newname):
self.log_frame()
def set_column0_contents(index, ordinal, _inode):
if inode == _inode:
ordinal = self.chooser._get_ordinal_at(index)
self.chooser.netnode.supset(index, newname, SUPVAL_COL0_DATA_TAG)
return True
return self.chooser._for_each_item(set_column0_contents)
def unlink_inode(self, inode):
self.log_frame()
ALTVAL_NEW_ORDINAL_TAG = 'L'
ALTVAL_ORDINAL_TAG = 'O'
ALTVAL_INODE_TAG = 'I'
SUPVAL_COL0_DATA_TAG = '0'
SUPVAL_COL1_DATA_TAG = '1'
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,
title,
[
["First",
10
| ida_kernwin.Choose.CHCOL_PLAIN
| ida_kernwin.Choose.CHCOL_DRAGHINT
| ida_kernwin.Choose.CHCOL_INODENAME
],
["Second", 10 | ida_kernwin.Choose.CHCOL_PLAIN],
["Third", 10 | ida_kernwin.Choose.CHCOL_PLAIN],
],
flags=flags)
self.debug_items = False
self.dirspec_log = dirspec_log
self.dirtree = None
self.dirspec = None
self.netnode = ida_netnode.netnode()
self.netnode.create("$ idapython_tree_view %s" % title)
for i in range(nitems):
self._new_item()
def _get_new_ordinal(self):
return self.netnode.altval(0, ALTVAL_NEW_ORDINAL_TAG)
def _set_new_ordinal(self, ordinal):
self.netnode.altset(0, ordinal, ALTVAL_NEW_ORDINAL_TAG)
def _allocate_ordinal(self):
ordinal = self._get_new_ordinal()
self._set_new_ordinal(ordinal + 1)
return ordinal
def _move_items(self, src, dst, sz):
self.netnode.altshift(src, dst, sz, ALTVAL_ORDINAL_TAG)
self.netnode.altshift(src, dst, sz, ALTVAL_INODE_TAG)
self.netnode.supshift(src, dst, sz, SUPVAL_COL0_DATA_TAG)
self.netnode.supshift(src, dst, sz, SUPVAL_COL1_DATA_TAG)
self.netnode.supshift(src, dst, sz, SUPVAL_COL2_DATA_TAG)
def _new_item(self, index=None):
new_ord = self._allocate_ordinal()
new_inode = new_ord + 1000
nitems = self._get_items_count()
if index is None:
index = nitems
else:
assert(index < nitems)
if index < nitems:
self._move_items(index, index + 1, nitems - index)
self.netnode.altset(index, new_ord, ALTVAL_ORDINAL_TAG)
self.netnode.altset(index, new_inode, ALTVAL_INODE_TAG)
return index, new_ord, new_inode
def _dump_items(self):
if self.debug_items:
data = []
def collect(index, ordinal, inode):
data.append([inode] + self._make_item_contents_from_index(index))
self._for_each_item(collect)
import pprint
print(pprint.pformat(data))
def _get_ordinal_at(self, index):
assert(index <= self.netnode.altlast(ALTVAL_ORDINAL_TAG))
return self.netnode.altval(index, ALTVAL_ORDINAL_TAG)
def _get_inode_at(self, index):
assert(index <= self.netnode.altlast(ALTVAL_INODE_TAG))
return self.netnode.altval(index, ALTVAL_INODE_TAG)
def _for_each_item(self, cb):
for i in range(self._get_items_count()):
rc = cb(i, self._get_ordinal_at(i), self._get_inode_at(i))
if rc is not None:
return rc
def _get_items_count(self):
l = self.netnode.altlast(ALTVAL_ORDINAL_TAG)
return 0 if l == ida_netnode.BADNODE else l + 1
def _make_item_contents_from_index(self, index):
ordinal = self._get_ordinal_at(index)
c0 = self.netnode.supstr(index, SUPVAL_COL0_DATA_TAG) or "a%d" % ordinal
c1 = self.netnode.supstr(index, SUPVAL_COL1_DATA_TAG) or "b%d" % ordinal
c2 = self.netnode.supstr(index, SUPVAL_COL2_DATA_TAG) or "c%d" % ordinal
return [c0, c1, c2]
def OnGetLine(self, n):
return self._make_item_contents_from_index(n)
def OnGetSize(self):
return self._get_items_count()
def OnGetDirTree(self):
self.dirspec = my_dirspec_t(self)
self.dirtree = ida_dirtree.dirtree_t(self.dirspec)
def do_link(index, ordinal, inode):
de = ida_dirtree.direntry_t(inode, False)
self.dirtree.link("/%s" % self.dirtree.get_entry_name(de))
self._for_each_item(do_link)
return (self.dirspec, self.dirtree)
def OnIndexToInode(self, n):
return self._get_inode_at(n)
# Helper function, to be called by "On*" event handlers.
# This will print all the arguments that were passed
def _print_prev_frame(self):
import inspect
stack = inspect.stack()
frame, _, _, _, _, _ = stack[1]
args, _, _, values = inspect.getargvalues(frame)
print("EVENT: %s: args=%s" % (
inspect.getframeinfo(frame)[2],
[(i, values[i]) for i in args[1:]]))
def OnSelectionChange(self, sel):
self._print_prev_frame()
def OnSelectLine(self, sel):
self._print_prev_frame()
class idapython_tree_view_t(base_idapython_tree_view_t):
def __init__(self, title, nitems=100, dirspec_log=True, flags=0):
flags |= ida_kernwin.CH_CAN_INS
flags |= ida_kernwin.CH_CAN_DEL
flags |= ida_kernwin.CH_CAN_EDIT
base_idapython_tree_view_t.__init__(self, title, nitems, dirspec_log, flags)
def OnInsertLine(self, sel):
self._print_prev_frame()
# Add item into storage
index = sel[0] if sel else None
prev_inode = self._get_inode_at(index) if index is not None else None
final_index, new_ordinal, new_inode = self._new_item(sel[0] if sel else None)
# Link in the tree (unless an absolute path is provided,
# 'link()' will use the current directory, which is set
# by the 'OnInsertLine' caller.)
dt = self.dirtree
cwd = dt.getcwd()
parent_de = dt.resolve_path(cwd)
wanted_rank = -1
if prev_inode is not None:
wanted_rank = dt.get_rank(parent_de.idx, ida_dirtree.direntry_t(prev_inode, False))
de = ida_dirtree.direntry_t(new_inode, False)
name = dt.get_entry_name(de)
code = dt.link(name)
assert(code == ida_dirtree.DTE_OK)
if wanted_rank >= 0:
assert(ida_dirtree.dirtree_t.isdir(parent_de))
cur_rank = dt.get_rank(parent_de.idx, de)
dt.change_rank(cwd + "/" + name, wanted_rank - cur_rank)
self._dump_items()
return [ida_kernwin.Choose.ALL_CHANGED] + [final_index]
def OnDeleteLine(self, sel):
self._print_prev_frame()
dt = self.dirtree
for index in reversed(sorted(sel)):
# Note: when it comes to deletion of items, the dirtree_t is
# designed in such a way folders contents will be re-computed
# on-demand after the deletion of an inode. Consequently,
# there is no need to perform an unlink() operation here, only
# notify the dirtree that something changed
nitems = self._get_items_count()
assert(index < nitems)
inode = self._get_inode_at(index)
self.netnode.altdel(index, ALTVAL_ORDINAL_TAG)
self.netnode.altdel(index, ALTVAL_INODE_TAG)
self._move_items(index + 1, index, nitems - index + 1)
dt.notify_dirtree(False, inode)
self._dump_items()
return [ida_kernwin.Choose.ALL_CHANGED]
def OnEditLine(self, sel):
self._print_prev_frame()
for idx in sel:
repl = ida_kernwin.ask_str("", 0, "Please enter replacement for index %d" % idx)
if repl:
self.netnode.supset(idx, repl, SUPVAL_COL0_DATA_TAG)
self._dump_items()
return [ida_kernwin.Choose.ALL_CHANGED] + sel
@@ -1,7 +1,7 @@
#
# This example lets the user programmatically retrieve
# the strings currently selected in the "Strings window"
# the strings currently selected in the "Strings" window
#
import ida_kernwin
@@ -57,7 +57,7 @@ klasses = [
show_strings_using_get_strlist_item_ah_t,
]
sw = ida_kernwin.find_widget("Strings window")
sw = ida_kernwin.find_widget("Strings")
if not sw:
sw = ida_kernwin.open_strings_window(ida_idaapi.BADADDR)
+7 -5
View File
@@ -11,9 +11,8 @@
# include <windows.h>
#endif
#include <algorithm>
//lint -esym(1788, iinc) is referenced only by its constructor or destructor
//lint -e754 local struct member 'pylib_entries_t::path_history' not referenced
#include <pro.h>
#include <err.h>
@@ -214,9 +213,7 @@ typedef qvector<pylib_entry_t> pylib_entry_vec_t;
struct pylib_entries_t
{
pylib_entry_vec_t entries;
#ifdef __MAC__
qstrvec_t path_history;
#endif
pylib_entry_t *get_entry_for_version(const pylib_version_t &version)
{
@@ -326,7 +323,12 @@ bool pyver_tool_t::do_pick_sip(
const pylib_entry_t &entry,
qstring *errbuf) const
{
const char *src_sip_subdir = entry.version.minor >= 9 ? "python_3.9"
#ifdef __MAC__
if ( entry.version.major == 2 )
return true; // nothing to do for Python2
#endif
const char *src_sip_subdir = entry.version.minor >= 10 ? "python_3.10"
: entry.version.minor >= 9 ? "python_3.9"
: entry.version.minor >= 8 ? "python_3.8"
: "python_3.4";
char src_sip_path[QMAXPATH];
+31
View File
@@ -476,6 +476,36 @@ bool pyver_tool_t::do_apply_version(
const pylib_entry_t &entry,
qstring *errbuf) const
{
#ifdef __APPLE_SILICON__
// modify the libpython symlink in idabin so that it points to the given libpython path
qstring link_name;
link_name.sprnt("libpython%d.link.dylib", entry.version.major);
char link_path[QMAXPATH];
qmakepath(link_path, sizeof(link_path), idadir(""), link_name.c_str(), nullptr);
if ( qfileexist(link_path) )
{
out_verb("Removing existing \"%s\"\n", link_path);
int rc = qunlink(link_path);
if ( rc != 0 )
{
errbuf->sprnt("Unlinking \"%s\" failed: %s", link_path, winerr(errno));
return false;
}
}
const char *target = entry.paths[0].c_str();
out_verb("Linking \"%s\" -> \"%s\"\n", link_path, target);
int rc = symlink(target, link_path);
if ( rc != 0 )
{
errbuf->sprnt("Linking to \"%s\" failed: %s", target, winerr(errno));
return false;
}
return true;
#else
// patch the libpython load commands in all idapython modules
struct ida_local patcher_t : public file_visitor_t
{
const pylib_entry_t &entry;
@@ -488,4 +518,5 @@ bool pyver_tool_t::do_apply_version(
};
patcher_t patcher(entry, errbuf);
return for_all_plugin_files(patcher, patcher.lerrbuf) == 0;
#endif
}
+8 -7
View File
@@ -191,7 +191,7 @@ static bool is_python3Y_dll_file_name(const char *fname)
return fname != nullptr
&& strnieq(fname, "python3", 7)
&& qisdigit(fname[7])
&& strieq(&fname[8], ".dll");
&& strieq(get_file_ext(fname), "dll");
}
#include <exehdr.h>
@@ -303,7 +303,7 @@ static bool has_appx_path(qstrvec_t paths)
//-------------------------------------------------------------------------
// ignore known bad Pythons:
// 3.8.0 release (https://bugs.python.org/issue37633)
// Anaconda 2019.10 and 2020.02 (https://github.com/ContinuumIO/anaconda-issues/issues/11374)
// Anaconda 2019.10, 2020.02 and 2020.11 (https://github.com/ContinuumIO/anaconda-issues/issues/11374)
// AppStore Python on Windows 10 (dll can't be loaded from outside of Appx package)
static bool bad_entry(const pylib_entry_t &e)
{
@@ -315,7 +315,8 @@ static bool bad_entry(const pylib_entry_t &e)
return true;
}
if ( e.display_name == "Anaconda 2019.10"
|| e.display_name == "Anaconda 2020.02" )
|| e.display_name == "Anaconda 2020.02"
|| e.display_name == "Anaconda 2020.11" )
{
out("Ignoring unusable %s \"%s\"\n", e.display_name.c_str(), !e.paths.empty() ? e.paths[0].c_str() : "?");
return true;
@@ -371,7 +372,7 @@ static void enum_python_key(pylib_entries_t *result, const HKEY hkey, qstring *_
if ( RegOpenKeyExW(hkey, subkey, 0, KEY_READ, &ihkey) == ERROR_SUCCESS )
{
out_verb("Opened \"%ls\"\n", subkey);
//opened an install. get its version from SysVersion value
// opened an install. get its version from SysVersion value
qstring sysver;
pylib_version_t version;
bool ok = read_string(&sysver, ihkey, PYTHON_SYSVER_SUBKEY);
@@ -421,7 +422,7 @@ static void enum_python_key(pylib_entries_t *result, const HKEY hkey, qstring *_
}
else
{
out_verb("Couldn't open \"%s\"\n", subkey);
out("Couldn't open \"%s\"\n", subkey);
}
}
else
@@ -534,14 +535,14 @@ void pyver_tool_t::do_find_python_libs(pylib_entries_t *result) const
}
else
{
out_verb("\"%ls\" exists, but no \"%ls\" value found\n",
out("\"%ls\" exists, but no \"%ls\" value found\n",
IDA_ADDLIB_SUBKEY, IDA_ADDLIB_VALUE);
}
RegCloseKey(idahkey);
}
else
{
out_verb("No \"%ls\" key found\n", IDA_ADDLIB_SUBKEY);
out("No \"%ls\" key found\n", IDA_ADDLIB_SUBKEY);
}
}
}
+7 -5
View File
@@ -441,13 +441,15 @@ static void handle_python_error(
}
//-------------------------------------------------------------------------
static const char *insert_coding_cookie(qstring *out)
#define ENCODING_COOKIE "# -*- coding: UTF-8 -*-\n"
#define ENCODING_COOKIE_LEN 24
static const char *insert_encoding_cookie(qstring *out)
{
// This is necessary for pre-3.9 parsers, to parse the
// input text as proper UTF-8. Python 3.9 switches to the PEG
// parser that, by default (and in particular since we don't
// pass PyCompilerFlags), will always assume UTF-8.
out->insert(0, "# -*- coding: UTF-8 -*-\n");
out->insert(0, ENCODING_COOKIE, ENCODING_COOKIE_LEN);
return out->c_str();
}
@@ -1322,7 +1324,7 @@ bool idapython_plugin_t::_extlang_compile_expr(
bool isfunc = false;
qstring qstr(expr);
PyObject *code = my_CompileString(insert_coding_cookie(&qstr), "<string>", Py_eval_input);
PyObject *code = my_CompileString(insert_encoding_cookie(&qstr), "<string>", Py_eval_input);
if ( code == NULL )
{
// try compiling as a list of statements
@@ -1330,7 +1332,7 @@ bool idapython_plugin_t::_extlang_compile_expr(
handle_python_error(errbuf);
qstring func;
wrap_in_function(&func, expr, name);
insert_coding_cookie(&func);
insert_encoding_cookie(&func);
code = my_CompileString(func.c_str(), "<string>", Py_file_input);
if ( code == NULL )
{
@@ -1890,7 +1892,7 @@ bool idapython_plugin_t::_cli_execute_line(const char *line)
// Compile as an expression
qstring qstr(line);
newref_t py_code(my_CompileString(insert_coding_cookie(&qstr), "<string>", Py_eval_input));
newref_t py_code(my_CompileString(insert_encoding_cookie(&qstr), "<string>", Py_eval_input));
if ( py_code == NULL || PyErr_Occurred() )
{
// Not an expression?
+441
View File
@@ -0,0 +1,441 @@
--- !tapi-tbd
tbd-version: 4
targets: [ arm64e-macos ]
install-name: '@executable_path/libpython2.link.dylib'
current-version: 2.7.16
compatibility-version: 2.7
exports:
- targets: [ arm64e-macos ]
symbols: [ _AEDesc_Convert, _AEDesc_New, _AEDesc_NewBorrowed, _BMObj_Convert,
_BMObj_New, _CFArrayRefObj_Convert, _CFArrayRefObj_New, _CFDictionaryRefObj_Convert,
_CFDictionaryRefObj_New, _CFMutableArrayRefObj_Convert, _CFMutableArrayRefObj_New,
_CFMutableDictionaryRefObj_Convert, _CFMutableDictionaryRefObj_New,
_CFMutableStringRefObj_Convert, _CFMutableStringRefObj_New,
_CFObj_Convert, _CFObj_New, _CFStringRefObj_Convert, _CFStringRefObj_New,
_CFTypeRefObj_Convert, _CFTypeRefObj_New, _CFURLRefObj_Convert,
_CFURLRefObj_New, _CmpInstObj_Convert, _CmpInstObj_New, _CmpObj_Convert,
_CmpObj_New, _CtlObj_Convert, _CtlObj_New, _DlgObj_Convert,
_DlgObj_New, _DlgObj_WhichDialog, _DragObj_Convert, _DragObj_New,
_GWorldObj_Convert, _GWorldObj_New, _GrafObj_Convert, _GrafObj_New,
_ListObj_Convert, _ListObj_New, _MenuObj_Convert, _MenuObj_New,
_OptResObj_Convert, _OptResObj_New, _OptionalCFURLRefObj_Convert,
_PyAST_Check, _PyAST_Compile, _PyAST_FromNode, _PyAST_mod2obj,
_PyAST_obj2mod, _PyArena_AddPyObject, _PyArena_Free, _PyArena_Malloc,
_PyArena_New, _PyArg_Parse, _PyArg_ParseTuple, _PyArg_ParseTupleAndKeywords,
_PyArg_UnpackTuple, _PyArg_VaParse, _PyArg_VaParseTupleAndKeywords,
_PyBaseObject_Type, _PyBaseString_Type, _PyBool_FromLong,
_PyBool_Type, _PyBuffer_FillContiguousStrides, _PyBuffer_FillInfo,
_PyBuffer_FromContiguous, _PyBuffer_FromMemory, _PyBuffer_FromObject,
_PyBuffer_FromReadWriteMemory, _PyBuffer_FromReadWriteObject,
_PyBuffer_GetPointer, _PyBuffer_IsContiguous, _PyBuffer_New,
_PyBuffer_Release, _PyBuffer_ToContiguous, _PyBuffer_Type,
_PyByteArrayIter_Type, _PyByteArray_AsString, _PyByteArray_Concat,
_PyByteArray_Fini, _PyByteArray_FromObject, _PyByteArray_FromStringAndSize,
_PyByteArray_Init, _PyByteArray_Resize, _PyByteArray_Size,
_PyByteArray_Type, _PyCFunction_Call, _PyCFunction_ClearFreeList,
_PyCFunction_Fini, _PyCFunction_GetFlags, _PyCFunction_GetFunction,
_PyCFunction_GetSelf, _PyCFunction_New, _PyCFunction_NewEx,
_PyCFunction_Type, _PyCObject_AsVoidPtr, _PyCObject_FromVoidPtr,
_PyCObject_FromVoidPtrAndDesc, _PyCObject_GetDesc, _PyCObject_Import,
_PyCObject_SetVoidPtr, _PyCObject_Type, _PyCallIter_New, _PyCallIter_Type,
_PyCallable_Check, _PyCapsule_GetContext, _PyCapsule_GetDestructor,
_PyCapsule_GetName, _PyCapsule_GetPointer, _PyCapsule_Import,
_PyCapsule_IsValid, _PyCapsule_New, _PyCapsule_SetContext,
_PyCapsule_SetDestructor, _PyCapsule_SetName, _PyCapsule_SetPointer,
_PyCapsule_Type, _PyCell_Get, _PyCell_New, _PyCell_Set, _PyCell_Type,
_PyClassMethod_New, _PyClassMethod_Type, _PyClass_IsSubclass,
_PyClass_New, _PyClass_Type, _PyCode_Addr2Line, _PyCode_New,
_PyCode_NewEmpty, _PyCode_Optimize, _PyCode_Type, _PyCodec_BackslashReplaceErrors,
_PyCodec_Decode, _PyCodec_Decoder, _PyCodec_Encode, _PyCodec_Encoder,
_PyCodec_IgnoreErrors, _PyCodec_IncrementalDecoder, _PyCodec_IncrementalEncoder,
_PyCodec_LookupError, _PyCodec_Register, _PyCodec_RegisterError,
_PyCodec_ReplaceErrors, _PyCodec_StreamReader, _PyCodec_StreamWriter,
_PyCodec_StrictErrors, _PyCodec_XMLCharRefReplaceErrors, _PyComplex_AsCComplex,
_PyComplex_FromCComplex, _PyComplex_FromDoubles, _PyComplex_ImagAsDouble,
_PyComplex_RealAsDouble, _PyComplex_Type, _PyDescr_NewClassMethod,
_PyDescr_NewGetSet, _PyDescr_NewMember, _PyDescr_NewMethod,
_PyDescr_NewWrapper, _PyDictItems_Type, _PyDictIterItem_Type,
_PyDictIterKey_Type, _PyDictIterValue_Type, _PyDictKeys_Type,
_PyDictProxy_New, _PyDictProxy_Type, _PyDictValues_Type, _PyDict_Clear,
_PyDict_Contains, _PyDict_Copy, _PyDict_DelItem, _PyDict_DelItemString,
_PyDict_Fini, _PyDict_GetItem, _PyDict_GetItemString, _PyDict_Items,
_PyDict_Keys, _PyDict_Merge, _PyDict_MergeFromSeq2, _PyDict_New,
_PyDict_Next, _PyDict_SetItem, _PyDict_SetItemString, _PyDict_Size,
_PyDict_Type, _PyDict_Update, _PyDict_Values, _PyEllipsis_Type,
_PyEnum_Type, _PyErr_BadArgument, _PyErr_BadInternalCall,
_PyErr_CheckSignals, _PyErr_Clear, _PyErr_Display, _PyErr_ExceptionMatches,
_PyErr_Fetch, _PyErr_Format, _PyErr_GivenExceptionMatches,
_PyErr_Mac, _PyErr_NewException, _PyErr_NewExceptionWithDoc,
_PyErr_NoMemory, _PyErr_NormalizeException, _PyErr_Occurred,
_PyErr_Print, _PyErr_PrintEx, _PyErr_ProgramText, _PyErr_Restore,
_PyErr_SetFromErrno, _PyErr_SetFromErrnoWithFilename, _PyErr_SetFromErrnoWithFilenameObject,
_PyErr_SetInterrupt, _PyErr_SetNone, _PyErr_SetObject, _PyErr_SetString,
_PyErr_SyntaxLocation, _PyErr_Warn, _PyErr_WarnEx, _PyErr_WarnExplicit,
_PyErr_WriteUnraisable, _PyEval_AcquireLock, _PyEval_AcquireThread,
_PyEval_CallFunction, _PyEval_CallMethod, _PyEval_CallObjectWithKeywords,
_PyEval_EvalCode, _PyEval_EvalCodeEx, _PyEval_EvalFrame, _PyEval_EvalFrameEx,
_PyEval_GetBuiltins, _PyEval_GetCallStats, _PyEval_GetFrame,
_PyEval_GetFuncDesc, _PyEval_GetFuncName, _PyEval_GetGlobals,
_PyEval_GetLocals, _PyEval_GetRestricted, _PyEval_InitThreads,
_PyEval_MergeCompilerFlags, _PyEval_ReInitThreads, _PyEval_ReleaseLock,
_PyEval_ReleaseThread, _PyEval_RestoreThread, _PyEval_SaveThread,
_PyEval_SetProfile, _PyEval_SetTrace, _PyEval_ThreadsInitialized,
_PyExc_ArithmeticError, _PyExc_AssertionError, _PyExc_AttributeError,
_PyExc_BaseException, _PyExc_BufferError, _PyExc_BytesWarning,
_PyExc_DeprecationWarning, _PyExc_EOFError, _PyExc_EnvironmentError,
_PyExc_Exception, _PyExc_FloatingPointError, _PyExc_FutureWarning,
_PyExc_GeneratorExit, _PyExc_IOError, _PyExc_ImportError,
_PyExc_ImportWarning, _PyExc_IndentationError, _PyExc_IndexError,
_PyExc_KeyError, _PyExc_KeyboardInterrupt, _PyExc_LookupError,
_PyExc_MemoryError, _PyExc_MemoryErrorInst, _PyExc_NameError,
_PyExc_NotImplementedError, _PyExc_OSError, _PyExc_OverflowError,
_PyExc_PendingDeprecationWarning, _PyExc_RecursionErrorInst,
_PyExc_ReferenceError, _PyExc_RuntimeError, _PyExc_RuntimeWarning,
_PyExc_StandardError, _PyExc_StopIteration, _PyExc_SyntaxError,
_PyExc_SyntaxWarning, _PyExc_SystemError, _PyExc_SystemExit,
_PyExc_TabError, _PyExc_TypeError, _PyExc_UnboundLocalError,
_PyExc_UnicodeDecodeError, _PyExc_UnicodeEncodeError, _PyExc_UnicodeError,
_PyExc_UnicodeTranslateError, _PyExc_UnicodeWarning, _PyExc_UserWarning,
_PyExc_ValueError, _PyExc_Warning, _PyExc_ZeroDivisionError,
_PyFPE_dummy, _PyFile_AsFile, _PyFile_DecUseCount, _PyFile_FromFile,
_PyFile_FromString, _PyFile_GetLine, _PyFile_IncUseCount,
_PyFile_Name, _PyFile_SetBufSize, _PyFile_SetEncoding, _PyFile_SetEncodingAndErrors,
_PyFile_SoftSpace, _PyFile_Type, _PyFile_WriteObject, _PyFile_WriteString,
_PyFloat_AsDouble, _PyFloat_AsReprString, _PyFloat_AsString,
_PyFloat_ClearFreeList, _PyFloat_Fini, _PyFloat_FromDouble,
_PyFloat_FromString, _PyFloat_GetInfo, _PyFloat_GetMax, _PyFloat_GetMin,
_PyFloat_Type, _PyFrame_BlockPop, _PyFrame_BlockSetup, _PyFrame_ClearFreeList,
_PyFrame_FastToLocals, _PyFrame_Fini, _PyFrame_GetLineNumber,
_PyFrame_LocalsToFast, _PyFrame_New, _PyFrame_Type, _PyFrozenSet_New,
_PyFrozenSet_Type, _PyFunction_GetClosure, _PyFunction_GetCode,
_PyFunction_GetDefaults, _PyFunction_GetGlobals, _PyFunction_GetModule,
_PyFunction_New, _PyFunction_SetClosure, _PyFunction_SetDefaults,
_PyFunction_Type, _PyFuture_FromAST, _PyGC_Collect, _PyGILState_Ensure,
_PyGILState_GetThisThreadState, _PyGILState_Release, _PyGen_NeedsFinalizing,
_PyGen_New, _PyGen_Type, _PyGetSetDescr_Type, _PyGrammar_AddAccelerators,
_PyGrammar_FindDFA, _PyGrammar_LabelRepr, _PyGrammar_RemoveAccelerators,
_PyImport_AddModule, _PyImport_AppendInittab, _PyImport_Cleanup,
_PyImport_ExecCodeModule, _PyImport_ExecCodeModuleEx, _PyImport_ExtendInittab,
_PyImport_FrozenModules, _PyImport_GetImporter, _PyImport_GetMagicNumber,
_PyImport_GetModuleDict, _PyImport_Import, _PyImport_ImportFrozenModule,
_PyImport_ImportModule, _PyImport_ImportModuleLevel, _PyImport_ImportModuleNoBlock,
_PyImport_Inittab, _PyImport_ReloadModule, _PyInstance_New,
_PyInstance_NewRaw, _PyInstance_Type, _PyInt_AsLong, _PyInt_AsSsize_t,
_PyInt_AsUnsignedLongLongMask, _PyInt_AsUnsignedLongMask,
_PyInt_ClearFreeList, _PyInt_Fini, _PyInt_FromLong, _PyInt_FromSize_t,
_PyInt_FromSsize_t, _PyInt_FromString, _PyInt_FromUnicode,
_PyInt_GetMax, _PyInt_Type, _PyInterpreterState_Clear, _PyInterpreterState_Delete,
_PyInterpreterState_Head, _PyInterpreterState_New, _PyInterpreterState_Next,
_PyInterpreterState_ThreadHead, _PyIter_Next, _PyListIter_Type,
_PyListRevIter_Type, _PyList_Append, _PyList_AsTuple, _PyList_Fini,
_PyList_GetItem, _PyList_GetSlice, _PyList_Insert, _PyList_New,
_PyList_Reverse, _PyList_SetItem, _PyList_SetSlice, _PyList_Size,
_PyList_Sort, _PyList_Type, _PyLong_AsDouble, _PyLong_AsLong,
_PyLong_AsLongAndOverflow, _PyLong_AsLongLong, _PyLong_AsLongLongAndOverflow,
_PyLong_AsSsize_t, _PyLong_AsUnsignedLong, _PyLong_AsUnsignedLongLong,
_PyLong_AsUnsignedLongLongMask, _PyLong_AsUnsignedLongMask,
_PyLong_AsVoidPtr, _PyLong_FromDouble, _PyLong_FromLong, _PyLong_FromLongLong,
_PyLong_FromSize_t, _PyLong_FromSsize_t, _PyLong_FromString,
_PyLong_FromUnicode, _PyLong_FromUnsignedLong, _PyLong_FromUnsignedLongLong,
_PyLong_FromVoidPtr, _PyLong_GetInfo, _PyLong_Type, _PyMacGluePtr_AEDesc_Convert,
_PyMacGluePtr_AEDesc_New, _PyMacGluePtr_AEDesc_NewBorrowed,
_PyMacGluePtr_BMObj_Convert, _PyMacGluePtr_BMObj_New, _PyMacGluePtr_CFArrayRefObj_Convert,
_PyMacGluePtr_CFArrayRefObj_New, _PyMacGluePtr_CFDictionaryRefObj_Convert,
_PyMacGluePtr_CFDictionaryRefObj_New, _PyMacGluePtr_CFMutableArrayRefObj_Convert,
_PyMacGluePtr_CFMutableArrayRefObj_New, _PyMacGluePtr_CFMutableDictionaryRefObj_Convert,
_PyMacGluePtr_CFMutableDictionaryRefObj_New, _PyMacGluePtr_CFMutableStringRefObj_Convert,
_PyMacGluePtr_CFMutableStringRefObj_New, _PyMacGluePtr_CFObj_Convert,
_PyMacGluePtr_CFObj_New, _PyMacGluePtr_CFStringRefObj_Convert,
_PyMacGluePtr_CFStringRefObj_New, _PyMacGluePtr_CFTypeRefObj_Convert,
_PyMacGluePtr_CFTypeRefObj_New, _PyMacGluePtr_CFURLRefObj_Convert,
_PyMacGluePtr_CFURLRefObj_New, _PyMacGluePtr_CmpInstObj_Convert,
_PyMacGluePtr_CmpInstObj_New, _PyMacGluePtr_CmpObj_Convert,
_PyMacGluePtr_CmpObj_New, _PyMacGluePtr_CtlObj_Convert, _PyMacGluePtr_CtlObj_New,
_PyMacGluePtr_DlgObj_Convert, _PyMacGluePtr_DlgObj_New, _PyMacGluePtr_DlgObj_WhichDialog,
_PyMacGluePtr_DragObj_Convert, _PyMacGluePtr_DragObj_New,
_PyMacGluePtr_GWorldObj_Convert, _PyMacGluePtr_GWorldObj_New,
_PyMacGluePtr_GrafObj_Convert, _PyMacGluePtr_GrafObj_New,
_PyMacGluePtr_ListObj_Convert, _PyMacGluePtr_ListObj_New,
_PyMacGluePtr_MenuObj_Convert, _PyMacGluePtr_MenuObj_New,
_PyMacGluePtr_OptResObj_Convert, _PyMacGluePtr_OptResObj_New,
_PyMacGluePtr_OptionalCFURLRefObj_Convert, _PyMacGluePtr_PyMac_BuildFSRef,
_PyMacGluePtr_PyMac_BuildFSSpec, _PyMacGluePtr_PyMac_GetFSRef,
_PyMacGluePtr_PyMac_GetFSSpec, _PyMacGluePtr_QdRGB_Convert,
_PyMacGluePtr_QdRGB_New, _PyMacGluePtr_ResObj_Convert, _PyMacGluePtr_ResObj_New,
_PyMacGluePtr_TEObj_Convert, _PyMacGluePtr_TEObj_New, _PyMacGluePtr_WinObj_Convert,
_PyMacGluePtr_WinObj_New, _PyMacGluePtr_WinObj_WhichWindow,
_PyMac_BuildEventRecord, _PyMac_BuildFSRef, _PyMac_BuildFSSpec,
_PyMac_BuildFixed, _PyMac_BuildNumVersion, _PyMac_BuildOSType,
_PyMac_BuildOptStr255, _PyMac_BuildPoint, _PyMac_BuildRect,
_PyMac_BuildStr255, _PyMac_Buildwide, _PyMac_Error, _PyMac_GetEventRecord,
_PyMac_GetFSRef, _PyMac_GetFSSpec, _PyMac_GetFixed, _PyMac_GetOSErrException,
_PyMac_GetOSType, _PyMac_GetPoint, _PyMac_GetRect, _PyMac_GetStr255,
_PyMac_Getwide, _PyMac_OSErrException, _PyMac_StrError, _PyMapping_Check,
_PyMapping_GetItemString, _PyMapping_HasKey, _PyMapping_HasKeyString,
_PyMapping_Length, _PyMapping_SetItemString, _PyMapping_Size,
_PyMarshal_Init, _PyMarshal_ReadLastObjectFromFile, _PyMarshal_ReadLongFromFile,
_PyMarshal_ReadObjectFromFile, _PyMarshal_ReadObjectFromString,
_PyMarshal_ReadShortFromFile, _PyMarshal_WriteLongToFile,
_PyMarshal_WriteObjectToFile, _PyMarshal_WriteObjectToString,
_PyMem_Free, _PyMem_Malloc, _PyMem_Realloc, _PyMemberDescr_Type,
_PyMember_Get, _PyMember_GetOne, _PyMember_Set, _PyMember_SetOne,
_PyMemoryView_FromBuffer, _PyMemoryView_FromObject, _PyMemoryView_GetContiguous,
_PyMemoryView_Type, _PyMethod_Class, _PyMethod_ClearFreeList,
_PyMethod_Fini, _PyMethod_Function, _PyMethod_New, _PyMethod_Self,
_PyMethod_Type, _PyModule_AddIntConstant, _PyModule_AddObject,
_PyModule_AddStringConstant, _PyModule_GetDict, _PyModule_GetFilename,
_PyModule_GetName, _PyModule_GetWarningsModule, _PyModule_New,
_PyModule_Type, _PyNode_AddChild, _PyNode_Compile, _PyNode_Free,
_PyNode_ListTree, _PyNode_New, _PyNullImporter_Type, _PyNumber_Absolute,
_PyNumber_Add, _PyNumber_And, _PyNumber_AsSsize_t, _PyNumber_Check,
_PyNumber_Coerce, _PyNumber_CoerceEx, _PyNumber_Divide, _PyNumber_Divmod,
_PyNumber_Float, _PyNumber_FloorDivide, _PyNumber_InPlaceAdd,
_PyNumber_InPlaceAnd, _PyNumber_InPlaceDivide, _PyNumber_InPlaceFloorDivide,
_PyNumber_InPlaceLshift, _PyNumber_InPlaceMultiply, _PyNumber_InPlaceOr,
_PyNumber_InPlacePower, _PyNumber_InPlaceRemainder, _PyNumber_InPlaceRshift,
_PyNumber_InPlaceSubtract, _PyNumber_InPlaceTrueDivide, _PyNumber_InPlaceXor,
_PyNumber_Index, _PyNumber_Int, _PyNumber_Invert, _PyNumber_Long,
_PyNumber_Lshift, _PyNumber_Multiply, _PyNumber_Negative,
_PyNumber_Or, _PyNumber_Positive, _PyNumber_Power, _PyNumber_Remainder,
_PyNumber_Rshift, _PyNumber_Subtract, _PyNumber_ToBase, _PyNumber_TrueDivide,
_PyNumber_Xor, _PyOS_AfterFork, _PyOS_FiniInterrupts, _PyOS_InitInterrupts,
_PyOS_InputHook, _PyOS_InterruptOccurred, _PyOS_Readline,
_PyOS_ReadlineFunctionPointer, _PyOS_StdioReadline, _PyOS_ascii_atof,
_PyOS_ascii_formatd, _PyOS_ascii_strtod, _PyOS_double_to_string,
_PyOS_getsig, _PyOS_mystricmp, _PyOS_mystrnicmp, _PyOS_setsig,
_PyOS_snprintf, _PyOS_string_to_double, _PyOS_strtol, _PyOS_strtoul,
_PyOS_vsnprintf, _PyObject_AsCharBuffer, _PyObject_AsFileDescriptor,
_PyObject_AsReadBuffer, _PyObject_AsWriteBuffer, _PyObject_Call,
_PyObject_CallFunction, _PyObject_CallFunctionObjArgs, _PyObject_CallMethod,
_PyObject_CallMethodObjArgs, _PyObject_CallObject, _PyObject_CheckReadBuffer,
_PyObject_ClearWeakRefs, _PyObject_Cmp, _PyObject_Compare,
_PyObject_CopyData, _PyObject_DelItem, _PyObject_DelItemString,
_PyObject_Dir, _PyObject_Format, _PyObject_Free, _PyObject_GC_Del,
_PyObject_GC_Track, _PyObject_GC_UnTrack, _PyObject_GenericGetAttr,
_PyObject_GenericSetAttr, _PyObject_GetAttr, _PyObject_GetAttrString,
_PyObject_GetBuffer, _PyObject_GetItem, _PyObject_GetIter,
_PyObject_HasAttr, _PyObject_HasAttrString, _PyObject_Hash,
_PyObject_HashNotImplemented, _PyObject_Init, _PyObject_InitVar,
_PyObject_IsInstance, _PyObject_IsSubclass, _PyObject_IsTrue,
_PyObject_Length, _PyObject_Malloc, _PyObject_Not, _PyObject_Print,
_PyObject_Realloc, _PyObject_Repr, _PyObject_RichCompare,
_PyObject_RichCompareBool, _PyObject_SelfIter, _PyObject_SetAttr,
_PyObject_SetAttrString, _PyObject_SetItem, _PyObject_Size,
_PyObject_Str, _PyObject_Type, _PyObject_Unicode, _PyParser_ASTFromFile,
_PyParser_ASTFromString, _PyParser_AddToken, _PyParser_Delete,
_PyParser_New, _PyParser_ParseFile, _PyParser_ParseFileFlags,
_PyParser_ParseFileFlagsEx, _PyParser_ParseString, _PyParser_ParseStringFlags,
_PyParser_ParseStringFlagsFilename, _PyParser_ParseStringFlagsFilenameEx,
_PyParser_SetError, _PyParser_SimpleParseFile, _PyParser_SimpleParseFileFlags,
_PyParser_SimpleParseString, _PyParser_SimpleParseStringFilename,
_PyParser_SimpleParseStringFlags, _PyParser_SimpleParseStringFlagsFilename,
_PyProperty_Type, _PyRange_Type, _PyReversed_Type, _PyRun_AnyFile,
_PyRun_AnyFileEx, _PyRun_AnyFileExFlags, _PyRun_AnyFileFlags,
_PyRun_File, _PyRun_FileEx, _PyRun_FileExFlags, _PyRun_FileFlags,
_PyRun_InteractiveLoop, _PyRun_InteractiveLoopFlags, _PyRun_InteractiveOne,
_PyRun_InteractiveOneFlags, _PyRun_SimpleFile, _PyRun_SimpleFileEx,
_PyRun_SimpleFileExFlags, _PyRun_SimpleString, _PyRun_SimpleStringFlags,
_PyRun_String, _PyRun_StringFlags, _PySTEntry_Type, _PyST_GetScope,
_PySeqIter_New, _PySeqIter_Type, _PySequence_Check, _PySequence_Concat,
_PySequence_Contains, _PySequence_Count, _PySequence_DelItem,
_PySequence_DelSlice, _PySequence_Fast, _PySequence_GetItem,
_PySequence_GetSlice, _PySequence_In, _PySequence_InPlaceConcat,
_PySequence_InPlaceRepeat, _PySequence_Index, _PySequence_Length,
_PySequence_List, _PySequence_Repeat, _PySequence_SetItem,
_PySequence_SetSlice, _PySequence_Size, _PySequence_Tuple,
_PySet_Add, _PySet_Clear, _PySet_Contains, _PySet_Discard,
_PySet_Fini, _PySet_New, _PySet_Pop, _PySet_Size, _PySet_Type,
_PySignal_SetWakeupFd, _PySlice_GetIndices, _PySlice_GetIndicesEx,
_PySlice_New, _PySlice_Type, _PyStaticMethod_New, _PyStaticMethod_Type,
_PyString_AsDecodedObject, _PyString_AsDecodedString, _PyString_AsEncodedObject,
_PyString_AsEncodedString, _PyString_AsString, _PyString_AsStringAndSize,
_PyString_Concat, _PyString_ConcatAndDel, _PyString_Decode,
_PyString_DecodeEscape, _PyString_Encode, _PyString_Fini,
_PyString_Format, _PyString_FromFormat, _PyString_FromFormatV,
_PyString_FromString, _PyString_FromStringAndSize, _PyString_InternFromString,
_PyString_InternImmortal, _PyString_InternInPlace, _PyString_Repr,
_PyString_Size, _PyString_Type, _PyStructSequence_InitType,
_PyStructSequence_New, _PyStructSequence_UnnamedField, _PySuper_Type,
_PySymtable_Build, _PySymtable_Free, _PySymtable_Lookup, _PySys_AddWarnOption,
_PySys_GetFile, _PySys_GetObject, _PySys_HasWarnOptions, _PySys_ResetWarnOptions,
_PySys_SetArgv, _PySys_SetArgvEx, _PySys_SetObject, _PySys_SetPath,
_PySys_WriteStderr, _PySys_WriteStdout, _PyThreadState_Clear,
_PyThreadState_Delete, _PyThreadState_DeleteCurrent, _PyThreadState_Get,
_PyThreadState_GetDict, _PyThreadState_New, _PyThreadState_Next,
_PyThreadState_SetAsyncExc, _PyThreadState_Swap, _PyThread_ReInitTLS,
_PyThread_acquire_lock, _PyThread_allocate_lock, _PyThread_create_key,
_PyThread_delete_key, _PyThread_delete_key_value, _PyThread_exit_thread,
_PyThread_free_lock, _PyThread_get_key_value, _PyThread_get_stacksize,
_PyThread_get_thread_ident, _PyThread_init_thread, _PyThread_release_lock,
_PyThread_set_key_value, _PyThread_set_stacksize, _PyThread_start_new_thread,
_PyToken_OneChar, _PyToken_ThreeChars, _PyToken_TwoChars,
_PyTokenizer_Free, _PyTokenizer_FromFile, _PyTokenizer_FromString,
_PyTokenizer_Get, _PyTokenizer_RestoreEncoding, _PyTraceBack_Here,
_PyTraceBack_Print, _PyTraceBack_Type, _PyTupleIter_Type,
_PyTuple_ClearFreeList, _PyTuple_Fini, _PyTuple_GetItem, _PyTuple_GetSlice,
_PyTuple_New, _PyTuple_Pack, _PyTuple_SetItem, _PyTuple_Size,
_PyTuple_Type, _PyType_ClearCache, _PyType_GenericAlloc, _PyType_GenericNew,
_PyType_IsSubtype, _PyType_Modified, _PyType_Ready, _PyType_Type,
_PyUnicodeDecodeError_Create, _PyUnicodeDecodeError_GetEncoding,
_PyUnicodeDecodeError_GetEnd, _PyUnicodeDecodeError_GetObject,
_PyUnicodeDecodeError_GetReason, _PyUnicodeDecodeError_GetStart,
_PyUnicodeDecodeError_SetEnd, _PyUnicodeDecodeError_SetReason,
_PyUnicodeDecodeError_SetStart, _PyUnicodeEncodeError_Create,
_PyUnicodeEncodeError_GetEncoding, _PyUnicodeEncodeError_GetEnd,
_PyUnicodeEncodeError_GetObject, _PyUnicodeEncodeError_GetReason,
_PyUnicodeEncodeError_GetStart, _PyUnicodeEncodeError_SetEnd,
_PyUnicodeEncodeError_SetReason, _PyUnicodeEncodeError_SetStart,
_PyUnicodeTranslateError_Create, _PyUnicodeTranslateError_GetEnd,
_PyUnicodeTranslateError_GetObject, _PyUnicodeTranslateError_GetReason,
_PyUnicodeTranslateError_GetStart, _PyUnicodeTranslateError_SetEnd,
_PyUnicodeTranslateError_SetReason, _PyUnicodeTranslateError_SetStart,
_PyUnicodeUCS2_AsASCIIString, _PyUnicodeUCS2_AsCharmapString,
_PyUnicodeUCS2_AsEncodedObject, _PyUnicodeUCS2_AsEncodedString,
_PyUnicodeUCS2_AsLatin1String, _PyUnicodeUCS2_AsRawUnicodeEscapeString,
_PyUnicodeUCS2_AsUTF16String, _PyUnicodeUCS2_AsUTF32String,
_PyUnicodeUCS2_AsUTF8String, _PyUnicodeUCS2_AsUnicode, _PyUnicodeUCS2_AsUnicodeEscapeString,
_PyUnicodeUCS2_AsWideChar, _PyUnicodeUCS2_ClearFreelist, _PyUnicodeUCS2_Compare,
_PyUnicodeUCS2_Concat, _PyUnicodeUCS2_Contains, _PyUnicodeUCS2_Count,
_PyUnicodeUCS2_Decode, _PyUnicodeUCS2_DecodeASCII, _PyUnicodeUCS2_DecodeCharmap,
_PyUnicodeUCS2_DecodeLatin1, _PyUnicodeUCS2_DecodeRawUnicodeEscape,
_PyUnicodeUCS2_DecodeUTF16, _PyUnicodeUCS2_DecodeUTF16Stateful,
_PyUnicodeUCS2_DecodeUTF32, _PyUnicodeUCS2_DecodeUTF32Stateful,
_PyUnicodeUCS2_DecodeUTF8, _PyUnicodeUCS2_DecodeUTF8Stateful,
_PyUnicodeUCS2_DecodeUnicodeEscape, _PyUnicodeUCS2_Encode,
_PyUnicodeUCS2_EncodeASCII, _PyUnicodeUCS2_EncodeCharmap,
_PyUnicodeUCS2_EncodeDecimal, _PyUnicodeUCS2_EncodeLatin1,
_PyUnicodeUCS2_EncodeRawUnicodeEscape, _PyUnicodeUCS2_EncodeUTF16,
_PyUnicodeUCS2_EncodeUTF32, _PyUnicodeUCS2_EncodeUTF8, _PyUnicodeUCS2_EncodeUnicodeEscape,
_PyUnicodeUCS2_Find, _PyUnicodeUCS2_Format, _PyUnicodeUCS2_FromEncodedObject,
_PyUnicodeUCS2_FromFormat, _PyUnicodeUCS2_FromFormatV, _PyUnicodeUCS2_FromObject,
_PyUnicodeUCS2_FromOrdinal, _PyUnicodeUCS2_FromString, _PyUnicodeUCS2_FromStringAndSize,
_PyUnicodeUCS2_FromUnicode, _PyUnicodeUCS2_FromWideChar, _PyUnicodeUCS2_GetDefaultEncoding,
_PyUnicodeUCS2_GetMax, _PyUnicodeUCS2_GetSize, _PyUnicodeUCS2_Join,
_PyUnicodeUCS2_Partition, _PyUnicodeUCS2_RPartition, _PyUnicodeUCS2_RSplit,
_PyUnicodeUCS2_Replace, _PyUnicodeUCS2_Resize, _PyUnicodeUCS2_RichCompare,
_PyUnicodeUCS2_SetDefaultEncoding, _PyUnicodeUCS2_Split, _PyUnicodeUCS2_Splitlines,
_PyUnicodeUCS2_Tailmatch, _PyUnicodeUCS2_Translate, _PyUnicodeUCS2_TranslateCharmap,
_PyUnicode_AsDecodedObject, _PyUnicode_BuildEncodingMap, _PyUnicode_DecodeUTF7,
_PyUnicode_DecodeUTF7Stateful, _PyUnicode_EncodeUTF7, _PyUnicode_Type,
_PyWeakref_GetObject, _PyWeakref_NewProxy, _PyWeakref_NewRef,
_PyWrapperDescr_Type, _PyWrapper_New, _Py_AddPendingCall,
_Py_AtExit, _Py_BuildValue, _Py_BytesWarningFlag, _Py_CompileString,
_Py_CompileStringFlags, _Py_DebugFlag, _Py_DecRef, _Py_DivisionWarningFlag,
_Py_DontWriteBytecodeFlag, _Py_EndInterpreter, _Py_Exit, _Py_FatalError,
_Py_FdIsInteractive, _Py_FileSystemDefaultEncoding, _Py_Finalize,
_Py_FindMethod, _Py_FindMethodInChain, _Py_FlushLine, _Py_FrozenFlag,
_Py_FrozenMain, _Py_GetArgcArgv, _Py_GetBuildInfo, _Py_GetCompiler,
_Py_GetCopyright, _Py_GetExecPrefix, _Py_GetPath, _Py_GetPlatform,
_Py_GetPrefix, _Py_GetProgramFullPath, _Py_GetProgramName,
_Py_GetPythonHome, _Py_GetRecursionLimit, _Py_GetVersion,
_Py_HashRandomizationFlag, _Py_IgnoreEnvironmentFlag, _Py_IncRef,
_Py_InitModule4_64, _Py_Initialize, _Py_InitializeEx, _Py_InspectFlag,
_Py_InteractiveFlag, _Py_IsInitialized, _Py_Main, _Py_MakePendingCalls,
_Py_NewInterpreter, _Py_NoSiteFlag, _Py_NoUserSiteDirectory,
_Py_OptimizeFlag, _Py_Py3kWarningFlag, _Py_ReprEnter, _Py_ReprLeave,
_Py_SetProgramName, _Py_SetPythonHome, _Py_SetRecursionLimit,
_Py_SubversionRevision, _Py_SubversionShortBranch, _Py_SymtableString,
_Py_TabcheckFlag, _Py_UnicodeFlag, _Py_UniversalNewlineFgets,
_Py_UniversalNewlineFread, _Py_UseClassExceptionsFlag, _Py_VaBuildValue,
_Py_VerboseFlag, _Py_meta_grammar, _Py_pgen, _QdRGB_Convert,
_QdRGB_New, _ResObj_Convert, _ResObj_New, _TEObj_Convert,
_TEObj_New, _WinObj_Convert, _WinObj_New, _WinObj_WhichWindow,
__PyArg_NoKeywords, __PyArg_ParseTupleAndKeywords_SizeT, __PyArg_ParseTuple_SizeT,
__PyArg_Parse_SizeT, __PyArg_VaParseTupleAndKeywords_SizeT,
__PyArg_VaParse_SizeT, __PyBuiltin_Init, __PyByteArray_empty_string,
__PyBytes_FormatAdvanced, __PyCode_CheckLineNumber, __PyCode_ConstantKey,
__PyCodecInfo_GetIncrementalDecoder, __PyCodecInfo_GetIncrementalEncoder,
__PyCodec_DecodeText, __PyCodec_EncodeText, __PyCodec_Lookup,
__PyCodec_LookupTextEncoding, __PyComplex_FormatAdvanced,
__PyDict_Contains, __PyDict_DelItemIf, __PyDict_GetItemWithError,
__PyDict_MaybeUntrack, __PyDict_NewPresized, __PyDict_Next,
__PyErr_BadInternalCall, __PyErr_ReplaceException, __PyEval_CallTracing,
__PyEval_SliceIndex, __PyEval_SliceIndexNotNone, __PyExc_Fini,
__PyExc_Init, __PyFile_SanitizeMode, __PyFloat_FormatAdvanced,
__PyFloat_Init, __PyFloat_Pack4, __PyFloat_Pack8, __PyFloat_Unpack4,
__PyFloat_Unpack8, __PyFrame_Init, __PyGC_Dump, __PyGC_generation0,
__PyGILState_Fini, __PyGILState_Init, __PyImportHooks_Init,
__PyImport_AcquireLock, __PyImport_DynLoadFiletab, __PyImport_Filetab,
__PyImport_FindExtension, __PyImport_FindModule, __PyImport_Fini,
__PyImport_FixupExtension, __PyImport_GetDynLoadFunc, __PyImport_Init,
__PyImport_Inittab, __PyImport_IsScript, __PyImport_LoadDynamicModule,
__PyImport_ReInitLock, __PyImport_ReleaseLock, __PyInstance_Lookup,
__PyInt_AsInt, __PyInt_Format, __PyInt_FormatAdvanced, __PyInt_FromGid,
__PyInt_FromUid, __PyInt_Init, __PyList_Extend, __PyLong_AsByteArray,
__PyLong_AsInt, __PyLong_Copy, __PyLong_DigitValue, __PyLong_Format,
__PyLong_FormatAdvanced, __PyLong_Frexp, __PyLong_FromByteArray,
__PyLong_Init, __PyLong_New, __PyLong_NumBits, __PyLong_Sign,
__PyModule_Clear, __PyNode_SizeOf, __PyNumber_ConvertIntegralToInt,
__PyOS_GetOpt, __PyOS_ReadlineTState, __PyOS_ResetGetOpt,
__PyOS_URandom, __PyOS_ascii_formatd, __PyOS_ascii_strtod,
__PyOS_mystrnicmp_hack, __PyOS_optarg, __PyOS_opterr, __PyOS_optind,
__PyObject_CallFunction_SizeT, __PyObject_CallMethod_SizeT,
__PyObject_Del, __PyObject_Dump, __PyObject_GC_Del, __PyObject_GC_Malloc,
__PyObject_GC_New, __PyObject_GC_NewVar, __PyObject_GC_Resize,
__PyObject_GC_Track, __PyObject_GC_UnTrack, __PyObject_GenericGetAttrWithDict,
__PyObject_GenericSetAttrWithDict, __PyObject_GetDictPtr,
__PyObject_LengthHint, __PyObject_LookupSpecial, __PyObject_New,
__PyObject_NewVar, __PyObject_NextNotImplemented, __PyObject_RealIsInstance,
__PyObject_RealIsSubclass, __PyObject_SlotCompare, __PyObject_Str,
__PyParser_Grammar, __PyParser_TokenNames, __PyRandom_Fini,
__PyRandom_Init, __PySequence_IterSearch, __PySet_Next, __PySet_NextEntry,
__PySet_Update, __PySlice_AdjustIndices, __PySlice_FromIndices,
__PySlice_Unpack, __PyString_Eq, __PyString_FormatLong, __PyString_InsertThousandsGrouping,
__PyString_Join, __PyString_Resize, __PySys_GetSizeOf, __PySys_Init,
__PyThreadState_Current, __PyThreadState_GetFrame, __PyThreadState_Init,
__PyThreadState_Prealloc, __PyThread_CurrentFrames, __PyTrash_delete_later,
__PyTrash_delete_nesting, __PyTrash_deposit_object, __PyTrash_destroy_chain,
__PyTrash_thread_deposit_object, __PyTrash_thread_destroy_chain,
__PyTuple_MaybeUntrack, __PyTuple_Resize, __PyType_Lookup,
__PyUnicodeUCS2_AsDefaultEncodedString, __PyUnicodeUCS2_Fini,
__PyUnicodeUCS2_Init, __PyUnicodeUCS2_IsAlpha, __PyUnicodeUCS2_IsDecimalDigit,
__PyUnicodeUCS2_IsDigit, __PyUnicodeUCS2_IsLinebreak, __PyUnicodeUCS2_IsLowercase,
__PyUnicodeUCS2_IsNumeric, __PyUnicodeUCS2_IsTitlecase, __PyUnicodeUCS2_IsUppercase,
__PyUnicodeUCS2_IsWhitespace, __PyUnicodeUCS2_ToDecimalDigit,
__PyUnicodeUCS2_ToDigit, __PyUnicodeUCS2_ToLowercase, __PyUnicodeUCS2_ToNumeric,
__PyUnicodeUCS2_ToTitlecase, __PyUnicodeUCS2_ToUppercase,
__PyUnicode_DecodeUnicodeInternal, __PyUnicode_FormatAdvanced,
__PyUnicode_TypeRecords, __PyUnicode_XStrip, __PyWarnings_Init,
__PyWeakref_CallableProxyType, __PyWeakref_ClearRef, __PyWeakref_GetWeakrefCount,
__PyWeakref_ProxyType, __PyWeakref_RefType, __Py_Assert, __Py_Assign,
__Py_Attribute, __Py_AugAssign, __Py_BinOp, __Py_BoolOp, __Py_Break,
__Py_BuildValue_SizeT, __Py_Call, __Py_CheckInterval, __Py_CheckRecursionLimit,
__Py_CheckRecursiveCall, __Py_ClassDef, __Py_Compare, __Py_Continue,
__Py_Delete, __Py_Dict, __Py_DictComp, __Py_DisplaySourceLine,
__Py_Ellipsis, __Py_EllipsisObject, __Py_ExceptHandler, __Py_Exec,
__Py_Expr, __Py_Expression, __Py_ExtSlice, __Py_For, __Py_FunctionDef,
__Py_GeneratorExp, __Py_Gid_Converter, __Py_Global, __Py_HashDouble,
__Py_HashPointer, __Py_HashSecret, __Py_If, __Py_IfExp, __Py_Import,
__Py_ImportFrom, __Py_Index, __Py_InsertThousandsGroupingLocale,
__Py_Interactive, __Py_Lambda, __Py_List, __Py_ListComp, __Py_Mangle,
__Py_Module, __Py_Name, __Py_NoneStruct, __Py_NotImplementedStruct,
__Py_Num, __Py_PackageContext, __Py_Pass, __Py_Print, __Py_QnewFlag,
__Py_Raise, __Py_ReadyTypes, __Py_ReleaseInternedStrings,
__Py_Repr, __Py_Return, __Py_Set, __Py_SetComp, __Py_Slice,
__Py_Str, __Py_Subscript, __Py_Suite, __Py_SwappedOp, __Py_Ticker,
__Py_TrueStruct, __Py_TryExcept, __Py_TryFinally, __Py_Tuple,
__Py_Uid_Converter, __Py_UnaryOp, __Py_VaBuildValue_SizeT,
__Py_While, __Py_With, __Py_Yield, __Py_ZeroStruct, __Py_abstract_hack,
__Py_add_one_to_index_C, __Py_add_one_to_index_F, __Py_addarc,
__Py_addbit, __Py_adddfa, __Py_addfirstsets, __Py_addlabel,
__Py_addstate, __Py_alias, __Py_arguments, __Py_ascii_whitespace,
__Py_bytes_capitalize, __Py_bytes_isalnum, __Py_bytes_isalpha,
__Py_bytes_isdigit, __Py_bytes_islower, __Py_bytes_isspace,
__Py_bytes_istitle, __Py_bytes_isupper, __Py_bytes_lower,
__Py_bytes_swapcase, __Py_bytes_title, __Py_bytes_upper, __Py_c_abs,
__Py_c_diff, __Py_c_neg, __Py_c_pow, __Py_c_prod, __Py_c_quot,
__Py_c_sum, __Py_capitalize__doc__, __Py_capsule_hack, __Py_cobject_hack,
__Py_comprehension, __Py_ctype_table, __Py_ctype_tolower,
__Py_ctype_toupper, __Py_delbitset, __Py_dg_dtoa, __Py_dg_freedtoa,
__Py_dg_strtod, __Py_double_round, __Py_findlabel, __Py_freegrammar,
__Py_gitidentifier, __Py_gitversion, __Py_isalnum__doc__,
__Py_isalpha__doc__, __Py_isdigit__doc__, __Py_islower__doc__,
__Py_isspace__doc__, __Py_istitle__doc__, __Py_isupper__doc__,
__Py_keyword, __Py_lower__doc__, __Py_mergebitset, __Py_meta_grammar,
__Py_newbitset, __Py_newgrammar, __Py_parse_inf_or_nan, __Py_pgen,
__Py_samebitset, __Py_swapcase__doc__, __Py_title__doc__,
__Py_translatelabels, __Py_upper__doc__, _asdl_int_seq_new,
_asdl_seq_new, _init_ast, _init_codecs, _init_sre, _init_symtable,
_init_weakref, _initerrno, _initgc, _initimp, _initposix,
_initpwd, _initsignal, _initthread, _initxxsubtype, _initzipimport ]
...
+552
View File
@@ -0,0 +1,552 @@
--- !tapi-tbd
tbd-version: 4
targets: [ arm64-macos ]
install-name: '@executable_path/libpython3.link.dylib'
current-version: 3.9
compatibility-version: 3.9
exports:
- targets: [ arm64-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,
_PyArg_UnpackTuple, _PyArg_VaParse, _PyArg_VaParseTupleAndKeywords,
_PyArg_ValidateKeywordArguments, _PyAsyncGen_New, _PyAsyncGen_Type,
_PyBaseObject_Type, _PyBool_FromLong, _PyBool_Type, _PyBuffer_FillContiguousStrides,
_PyBuffer_FillInfo, _PyBuffer_FromContiguous, _PyBuffer_GetPointer,
_PyBuffer_IsContiguous, _PyBuffer_Release, _PyBuffer_SizeFromFormat,
_PyBuffer_ToContiguous, _PyByteArrayIter_Type, _PyByteArray_AsString,
_PyByteArray_Concat, _PyByteArray_FromObject, _PyByteArray_FromStringAndSize,
_PyByteArray_Resize, _PyByteArray_Size, _PyByteArray_Type,
_PyBytesIter_Type, _PyBytes_AsString, _PyBytes_AsStringAndSize,
_PyBytes_Concat, _PyBytes_ConcatAndDel, _PyBytes_DecodeEscape,
_PyBytes_FromFormat, _PyBytes_FromFormatV, _PyBytes_FromObject,
_PyBytes_FromString, _PyBytes_FromStringAndSize, _PyBytes_Repr,
_PyBytes_Size, _PyBytes_Type, _PyCFunction_Call, _PyCFunction_GetFlags,
_PyCFunction_GetFunction, _PyCFunction_GetSelf, _PyCFunction_NewEx,
_PyCFunction_Type, _PyCMethod_New, _PyCMethod_Type, _PyCallIter_New,
_PyCallIter_Type, _PyCallable_Check, _PyCapsule_GetContext,
_PyCapsule_GetDestructor, _PyCapsule_GetName, _PyCapsule_GetPointer,
_PyCapsule_Import, _PyCapsule_IsValid, _PyCapsule_New, _PyCapsule_SetContext,
_PyCapsule_SetDestructor, _PyCapsule_SetName, _PyCapsule_SetPointer,
_PyCapsule_Type, _PyCell_Get, _PyCell_New, _PyCell_Set, _PyCell_Type,
_PyClassMethodDescr_Type, _PyClassMethod_New, _PyClassMethod_Type,
_PyCode_Addr2Line, _PyCode_New, _PyCode_NewEmpty, _PyCode_NewWithPosOnlyArgs,
_PyCode_Optimize, _PyCode_Type, _PyCodec_BackslashReplaceErrors,
_PyCodec_Decode, _PyCodec_Decoder, _PyCodec_Encode, _PyCodec_Encoder,
_PyCodec_IgnoreErrors, _PyCodec_IncrementalDecoder, _PyCodec_IncrementalEncoder,
_PyCodec_KnownEncoding, _PyCodec_LookupError, _PyCodec_NameReplaceErrors,
_PyCodec_Register, _PyCodec_RegisterError, _PyCodec_ReplaceErrors,
_PyCodec_StreamReader, _PyCodec_StreamWriter, _PyCodec_StrictErrors,
_PyCodec_XMLCharRefReplaceErrors, _PyCompile_OpcodeStackEffect,
_PyCompile_OpcodeStackEffectWithJump, _PyComplex_AsCComplex,
_PyComplex_FromCComplex, _PyComplex_FromDoubles, _PyComplex_ImagAsDouble,
_PyComplex_RealAsDouble, _PyComplex_Type, _PyConfig_Clear,
_PyConfig_InitIsolatedConfig, _PyConfig_InitPythonConfig,
_PyConfig_Read, _PyConfig_SetArgv, _PyConfig_SetBytesArgv,
_PyConfig_SetBytesString, _PyConfig_SetString, _PyConfig_SetWideStringList,
_PyContextToken_Type, _PyContextVar_Get, _PyContextVar_New,
_PyContextVar_Reset, _PyContextVar_Set, _PyContextVar_Type,
_PyContext_Copy, _PyContext_CopyCurrent, _PyContext_Enter,
_PyContext_Exit, _PyContext_New, _PyContext_Type, _PyCoro_New,
_PyCoro_Type, _PyDescr_NewClassMethod, _PyDescr_NewGetSet,
_PyDescr_NewMember, _PyDescr_NewMethod, _PyDescr_NewWrapper,
_PyDictItems_Type, _PyDictIterItem_Type, _PyDictIterKey_Type,
_PyDictIterValue_Type, _PyDictKeys_Type, _PyDictProxy_New,
_PyDictProxy_Type, _PyDictRevIterItem_Type, _PyDictRevIterKey_Type,
_PyDictRevIterValue_Type, _PyDictValues_Type, _PyDict_Clear,
_PyDict_Contains, _PyDict_Copy, _PyDict_DelItem, _PyDict_DelItemString,
_PyDict_GetItem, _PyDict_GetItemString, _PyDict_GetItemWithError,
_PyDict_Items, _PyDict_Keys, _PyDict_Merge, _PyDict_MergeFromSeq2,
_PyDict_New, _PyDict_Next, _PyDict_SetDefault, _PyDict_SetItem,
_PyDict_SetItemString, _PyDict_Size, _PyDict_Type, _PyDict_Update,
_PyDict_Values, _PyEllipsis_Type, _PyEnum_Type, _PyErr_BadArgument,
_PyErr_BadInternalCall, _PyErr_CheckSignals, _PyErr_Clear,
_PyErr_Display, _PyErr_ExceptionMatches, _PyErr_Fetch, _PyErr_Format,
_PyErr_FormatV, _PyErr_GetExcInfo, _PyErr_GivenExceptionMatches,
_PyErr_NewException, _PyErr_NewExceptionWithDoc, _PyErr_NoMemory,
_PyErr_NormalizeException, _PyErr_Occurred, _PyErr_Print,
_PyErr_PrintEx, _PyErr_ProgramText, _PyErr_ProgramTextObject,
_PyErr_ResourceWarning, _PyErr_Restore, _PyErr_SetExcInfo,
_PyErr_SetFromErrno, _PyErr_SetFromErrnoWithFilename, _PyErr_SetFromErrnoWithFilenameObject,
_PyErr_SetFromErrnoWithFilenameObjects, _PyErr_SetImportError,
_PyErr_SetImportErrorSubclass, _PyErr_SetInterrupt, _PyErr_SetNone,
_PyErr_SetObject, _PyErr_SetString, _PyErr_SyntaxLocation,
_PyErr_SyntaxLocationEx, _PyErr_SyntaxLocationObject, _PyErr_WarnEx,
_PyErr_WarnExplicit, _PyErr_WarnExplicitFormat, _PyErr_WarnExplicitObject,
_PyErr_WarnFormat, _PyErr_WriteUnraisable, _PyEval_AcquireLock,
_PyEval_AcquireThread, _PyEval_CallFunction, _PyEval_CallMethod,
_PyEval_CallObjectWithKeywords, _PyEval_EvalCode, _PyEval_EvalCodeEx,
_PyEval_EvalFrame, _PyEval_EvalFrameEx, _PyEval_GetBuiltins,
_PyEval_GetFrame, _PyEval_GetFuncDesc, _PyEval_GetFuncName,
_PyEval_GetGlobals, _PyEval_GetLocals, _PyEval_InitThreads,
_PyEval_MergeCompilerFlags, _PyEval_ReleaseLock, _PyEval_ReleaseThread,
_PyEval_RestoreThread, _PyEval_SaveThread, _PyEval_SetProfile,
_PyEval_SetTrace, _PyEval_ThreadsInitialized, _PyExc_ArithmeticError,
_PyExc_AssertionError, _PyExc_AttributeError, _PyExc_BaseException,
_PyExc_BlockingIOError, _PyExc_BrokenPipeError, _PyExc_BufferError,
_PyExc_BytesWarning, _PyExc_ChildProcessError, _PyExc_ConnectionAbortedError,
_PyExc_ConnectionError, _PyExc_ConnectionRefusedError, _PyExc_ConnectionResetError,
_PyExc_DeprecationWarning, _PyExc_EOFError, _PyExc_EnvironmentError,
_PyExc_Exception, _PyExc_FileExistsError, _PyExc_FileNotFoundError,
_PyExc_FloatingPointError, _PyExc_FutureWarning, _PyExc_GeneratorExit,
_PyExc_IOError, _PyExc_ImportError, _PyExc_ImportWarning,
_PyExc_IndentationError, _PyExc_IndexError, _PyExc_InterruptedError,
_PyExc_IsADirectoryError, _PyExc_KeyError, _PyExc_KeyboardInterrupt,
_PyExc_LookupError, _PyExc_MemoryError, _PyExc_ModuleNotFoundError,
_PyExc_NameError, _PyExc_NotADirectoryError, _PyExc_NotImplementedError,
_PyExc_OSError, _PyExc_OverflowError, _PyExc_PendingDeprecationWarning,
_PyExc_PermissionError, _PyExc_ProcessLookupError, _PyExc_RecursionError,
_PyExc_ReferenceError, _PyExc_ResourceWarning, _PyExc_RuntimeError,
_PyExc_RuntimeWarning, _PyExc_StopAsyncIteration, _PyExc_StopIteration,
_PyExc_SyntaxError, _PyExc_SyntaxWarning, _PyExc_SystemError,
_PyExc_SystemExit, _PyExc_TabError, _PyExc_TimeoutError, _PyExc_TypeError,
_PyExc_UnboundLocalError, _PyExc_UnicodeDecodeError, _PyExc_UnicodeEncodeError,
_PyExc_UnicodeError, _PyExc_UnicodeTranslateError, _PyExc_UnicodeWarning,
_PyExc_UserWarning, _PyExc_ValueError, _PyExc_Warning, _PyExc_ZeroDivisionError,
_PyExceptionClass_Name, _PyException_GetCause, _PyException_GetContext,
_PyException_GetTraceback, _PyException_SetCause, _PyException_SetContext,
_PyException_SetTraceback, _PyFile_FromFd, _PyFile_GetLine,
_PyFile_NewStdPrinter, _PyFile_OpenCode, _PyFile_OpenCodeObject,
_PyFile_SetOpenCodeHook, _PyFile_WriteObject, _PyFile_WriteString,
_PyFilter_Type, _PyFloat_AsDouble, _PyFloat_FromDouble, _PyFloat_FromString,
_PyFloat_GetInfo, _PyFloat_GetMax, _PyFloat_GetMin, _PyFloat_Type,
_PyFrame_BlockPop, _PyFrame_BlockSetup, _PyFrame_FastToLocals,
_PyFrame_FastToLocalsWithError, _PyFrame_GetBack, _PyFrame_GetCode,
_PyFrame_GetLineNumber, _PyFrame_LocalsToFast, _PyFrame_New,
_PyFrame_Type, _PyFrozenSet_New, _PyFrozenSet_Type, _PyFunction_GetAnnotations,
_PyFunction_GetClosure, _PyFunction_GetCode, _PyFunction_GetDefaults,
_PyFunction_GetGlobals, _PyFunction_GetKwDefaults, _PyFunction_GetModule,
_PyFunction_New, _PyFunction_NewWithQualName, _PyFunction_SetAnnotations,
_PyFunction_SetClosure, _PyFunction_SetDefaults, _PyFunction_SetKwDefaults,
_PyFunction_Type, _PyFuture_FromAST, _PyFuture_FromASTObject,
_PyGC_Collect, _PyGILState_Check, _PyGILState_Ensure, _PyGILState_GetThisThreadState,
_PyGILState_Release, _PyGen_New, _PyGen_NewWithQualName, _PyGen_Type,
_PyGetSetDescr_Type, _PyHash_GetFuncDef, _PyImport_AddModule,
_PyImport_AddModuleObject, _PyImport_AppendInittab, _PyImport_ExecCodeModule,
_PyImport_ExecCodeModuleEx, _PyImport_ExecCodeModuleObject,
_PyImport_ExecCodeModuleWithPathnames, _PyImport_ExtendInittab,
_PyImport_FrozenModules, _PyImport_GetImporter, _PyImport_GetMagicNumber,
_PyImport_GetMagicTag, _PyImport_GetModule, _PyImport_GetModuleDict,
_PyImport_Import, _PyImport_ImportFrozenModule, _PyImport_ImportFrozenModuleObject,
_PyImport_ImportModule, _PyImport_ImportModuleLevel, _PyImport_ImportModuleLevelObject,
_PyImport_ImportModuleNoBlock, _PyImport_Inittab, _PyImport_ReloadModule,
_PyIndex_Check, _PyInit__abc, _PyInit__ast, _PyInit__codecs,
_PyInit__collections, _PyInit__functools, _PyInit__imp, _PyInit__io,
_PyInit__locale, _PyInit__operator, _PyInit__peg_parser, _PyInit__signal,
_PyInit__sre, _PyInit__stat, _PyInit__string, _PyInit__symtable,
_PyInit__thread, _PyInit__tracemalloc, _PyInit__weakref, _PyInit_atexit,
_PyInit_errno, _PyInit_faulthandler, _PyInit_gc, _PyInit_itertools,
_PyInit_posix, _PyInit_pwd, _PyInit_time, _PyInit_xxsubtype,
_PyInstanceMethod_Function, _PyInstanceMethod_New, _PyInstanceMethod_Type,
_PyInterpreterState_Clear, _PyInterpreterState_Delete, _PyInterpreterState_Get,
_PyInterpreterState_GetDict, _PyInterpreterState_GetID, _PyInterpreterState_Head,
_PyInterpreterState_Main, _PyInterpreterState_New, _PyInterpreterState_Next,
_PyInterpreterState_ThreadHead, _PyIter_Check, _PyIter_Next,
_PyListIter_Type, _PyListRevIter_Type, _PyList_Append, _PyList_AsTuple,
_PyList_GetItem, _PyList_GetSlice, _PyList_Insert, _PyList_New,
_PyList_Reverse, _PyList_SetItem, _PyList_SetSlice, _PyList_Size,
_PyList_Sort, _PyList_Type, _PyLongRangeIter_Type, _PyLong_AsDouble,
_PyLong_AsLong, _PyLong_AsLongAndOverflow, _PyLong_AsLongLong,
_PyLong_AsLongLongAndOverflow, _PyLong_AsSize_t, _PyLong_AsSsize_t,
_PyLong_AsUnsignedLong, _PyLong_AsUnsignedLongLong, _PyLong_AsUnsignedLongLongMask,
_PyLong_AsUnsignedLongMask, _PyLong_AsVoidPtr, _PyLong_FromDouble,
_PyLong_FromLong, _PyLong_FromLongLong, _PyLong_FromSize_t,
_PyLong_FromSsize_t, _PyLong_FromString, _PyLong_FromUnicode,
_PyLong_FromUnicodeObject, _PyLong_FromUnsignedLong, _PyLong_FromUnsignedLongLong,
_PyLong_FromVoidPtr, _PyLong_GetInfo, _PyLong_Type, _PyMap_Type,
_PyMapping_Check, _PyMapping_GetItemString, _PyMapping_HasKey,
_PyMapping_HasKeyString, _PyMapping_Items, _PyMapping_Keys,
_PyMapping_Length, _PyMapping_SetItemString, _PyMapping_Size,
_PyMapping_Values, _PyMarshal_Init, _PyMarshal_ReadLastObjectFromFile,
_PyMarshal_ReadLongFromFile, _PyMarshal_ReadObjectFromFile,
_PyMarshal_ReadObjectFromString, _PyMarshal_ReadShortFromFile,
_PyMarshal_WriteLongToFile, _PyMarshal_WriteObjectToFile,
_PyMarshal_WriteObjectToString, _PyMem_Calloc, _PyMem_Free,
_PyMem_GetAllocator, _PyMem_Malloc, _PyMem_RawCalloc, _PyMem_RawFree,
_PyMem_RawMalloc, _PyMem_RawRealloc, _PyMem_Realloc, _PyMem_SetAllocator,
_PyMem_SetupDebugHooks, _PyMemberDescr_Type, _PyMember_GetOne,
_PyMember_SetOne, _PyMemoryView_FromBuffer, _PyMemoryView_FromMemory,
_PyMemoryView_FromObject, _PyMemoryView_GetContiguous, _PyMemoryView_Type,
_PyMethodDescr_Type, _PyMethod_Function, _PyMethod_New, _PyMethod_Self,
_PyMethod_Type, _PyModuleDef_Init, _PyModuleDef_Type, _PyModule_AddFunctions,
_PyModule_AddIntConstant, _PyModule_AddObject, _PyModule_AddStringConstant,
_PyModule_AddType, _PyModule_Create2, _PyModule_ExecDef, _PyModule_FromDefAndSpec2,
_PyModule_GetDef, _PyModule_GetDict, _PyModule_GetFilename,
_PyModule_GetFilenameObject, _PyModule_GetName, _PyModule_GetNameObject,
_PyModule_GetState, _PyModule_New, _PyModule_NewObject, _PyModule_SetDocString,
_PyModule_Type, _PyNode_AddChild, _PyNode_Compile, _PyNode_Free,
_PyNode_ListTree, _PyNode_New, _PyNumber_Absolute, _PyNumber_Add,
_PyNumber_And, _PyNumber_AsSsize_t, _PyNumber_Check, _PyNumber_Divmod,
_PyNumber_Float, _PyNumber_FloorDivide, _PyNumber_InPlaceAdd,
_PyNumber_InPlaceAnd, _PyNumber_InPlaceFloorDivide, _PyNumber_InPlaceLshift,
_PyNumber_InPlaceMatrixMultiply, _PyNumber_InPlaceMultiply,
_PyNumber_InPlaceOr, _PyNumber_InPlacePower, _PyNumber_InPlaceRemainder,
_PyNumber_InPlaceRshift, _PyNumber_InPlaceSubtract, _PyNumber_InPlaceTrueDivide,
_PyNumber_InPlaceXor, _PyNumber_Index, _PyNumber_Invert, _PyNumber_Long,
_PyNumber_Lshift, _PyNumber_MatrixMultiply, _PyNumber_Multiply,
_PyNumber_Negative, _PyNumber_Or, _PyNumber_Positive, _PyNumber_Power,
_PyNumber_Remainder, _PyNumber_Rshift, _PyNumber_Subtract,
_PyNumber_ToBase, _PyNumber_TrueDivide, _PyNumber_Xor, _PyODictItems_Type,
_PyODictIter_Type, _PyODictKeys_Type, _PyODictValues_Type,
_PyODict_DelItem, _PyODict_New, _PyODict_SetItem, _PyODict_Type,
_PyOS_AfterFork, _PyOS_AfterFork_Child, _PyOS_AfterFork_Parent,
_PyOS_BeforeFork, _PyOS_FSPath, _PyOS_InitInterrupts, _PyOS_InputHook,
_PyOS_InterruptOccurred, _PyOS_Readline, _PyOS_ReadlineFunctionPointer,
_PyOS_double_to_string, _PyOS_getsig, _PyOS_mystricmp, _PyOS_mystrnicmp,
_PyOS_setsig, _PyOS_snprintf, _PyOS_string_to_double, _PyOS_strtol,
_PyOS_strtoul, _PyOS_vsnprintf, _PyObject_ASCII, _PyObject_AsCharBuffer,
_PyObject_AsFileDescriptor, _PyObject_AsReadBuffer, _PyObject_AsWriteBuffer,
_PyObject_Bytes, _PyObject_Call, _PyObject_CallFinalizer,
_PyObject_CallFinalizerFromDealloc, _PyObject_CallFunction,
_PyObject_CallFunctionObjArgs, _PyObject_CallMethod, _PyObject_CallMethodObjArgs,
_PyObject_CallNoArgs, _PyObject_CallObject, _PyObject_Calloc,
_PyObject_CheckBuffer, _PyObject_CheckReadBuffer, _PyObject_ClearWeakRefs,
_PyObject_CopyData, _PyObject_DelItem, _PyObject_DelItemString,
_PyObject_Dir, _PyObject_Format, _PyObject_Free, _PyObject_GC_Del,
_PyObject_GC_IsFinalized, _PyObject_GC_IsTracked, _PyObject_GC_Track,
_PyObject_GC_UnTrack, _PyObject_GET_WEAKREFS_LISTPTR, _PyObject_GenericGetAttr,
_PyObject_GenericGetDict, _PyObject_GenericSetAttr, _PyObject_GenericSetDict,
_PyObject_GetArenaAllocator, _PyObject_GetAttr, _PyObject_GetAttrString,
_PyObject_GetBuffer, _PyObject_GetItem, _PyObject_GetIter,
_PyObject_HasAttr, _PyObject_HasAttrString, _PyObject_Hash,
_PyObject_HashNotImplemented, _PyObject_IS_GC, _PyObject_Init,
_PyObject_InitVar, _PyObject_IsInstance, _PyObject_IsSubclass,
_PyObject_IsTrue, _PyObject_Length, _PyObject_LengthHint,
_PyObject_Malloc, _PyObject_Not, _PyObject_Print, _PyObject_Realloc,
_PyObject_Repr, _PyObject_RichCompare, _PyObject_RichCompareBool,
_PyObject_SelfIter, _PyObject_SetArenaAllocator, _PyObject_SetAttr,
_PyObject_SetAttrString, _PyObject_SetItem, _PyObject_Size,
_PyObject_Str, _PyObject_Type, _PyObject_VectorcallDict, _PyObject_VectorcallMethod,
_PyParser_ASTFromFile, _PyParser_ASTFromFileObject, _PyParser_ASTFromString,
_PyParser_ASTFromStringObject, _PyParser_ClearError, _PyParser_ParseFile,
_PyParser_ParseFileFlags, _PyParser_ParseFileFlagsEx, _PyParser_ParseFileObject,
_PyParser_ParseString, _PyParser_ParseStringFlags, _PyParser_ParseStringFlagsFilename,
_PyParser_ParseStringFlagsFilenameEx, _PyParser_ParseStringObject,
_PyParser_SetError, _PyParser_SimpleParseFile, _PyParser_SimpleParseFileFlags,
_PyParser_SimpleParseString, _PyParser_SimpleParseStringFlags,
_PyParser_SimpleParseStringFlagsFilename, _PyPegen_ASTFromFileObject,
_PyPegen_ASTFromFilename, _PyPegen_ASTFromString, _PyPegen_ASTFromStringObject,
_PyPickleBuffer_FromObject, _PyPickleBuffer_GetBuffer, _PyPickleBuffer_Release,
_PyPickleBuffer_Type, _PyPreConfig_InitIsolatedConfig, _PyPreConfig_InitPythonConfig,
_PyProperty_Type, _PyRangeIter_Type, _PyRange_Type, _PyReversed_Type,
_PyRun_AnyFile, _PyRun_AnyFileEx, _PyRun_AnyFileExFlags, _PyRun_AnyFileFlags,
_PyRun_File, _PyRun_FileEx, _PyRun_FileExFlags, _PyRun_FileFlags,
_PyRun_InteractiveLoop, _PyRun_InteractiveLoopFlags, _PyRun_InteractiveOne,
_PyRun_InteractiveOneFlags, _PyRun_InteractiveOneObject, _PyRun_SimpleFile,
_PyRun_SimpleFileEx, _PyRun_SimpleFileExFlags, _PyRun_SimpleString,
_PyRun_SimpleStringFlags, _PyRun_String, _PyRun_StringFlags,
_PySTEntry_Type, _PyST_GetScope, _PySeqIter_New, _PySeqIter_Type,
_PySequence_Check, _PySequence_Concat, _PySequence_Contains,
_PySequence_Count, _PySequence_DelItem, _PySequence_DelSlice,
_PySequence_Fast, _PySequence_GetItem, _PySequence_GetSlice,
_PySequence_In, _PySequence_InPlaceConcat, _PySequence_InPlaceRepeat,
_PySequence_Index, _PySequence_Length, _PySequence_List, _PySequence_Repeat,
_PySequence_SetItem, _PySequence_SetSlice, _PySequence_Size,
_PySequence_Tuple, _PySetIter_Type, _PySet_Add, _PySet_Clear,
_PySet_Contains, _PySet_Discard, _PySet_New, _PySet_Pop, _PySet_Size,
_PySet_Type, _PySlice_AdjustIndices, _PySlice_GetIndices,
_PySlice_GetIndicesEx, _PySlice_New, _PySlice_Type, _PySlice_Unpack,
_PyState_AddModule, _PyState_FindModule, _PyState_RemoveModule,
_PyStaticMethod_New, _PyStaticMethod_Type, _PyStatus_Error,
_PyStatus_Exception, _PyStatus_Exit, _PyStatus_IsError, _PyStatus_IsExit,
_PyStatus_NoMemory, _PyStatus_Ok, _PyStdPrinter_Type, _PyStructSequence_GetItem,
_PyStructSequence_InitType, _PyStructSequence_InitType2, _PyStructSequence_New,
_PyStructSequence_NewType, _PyStructSequence_SetItem, _PySuper_Type,
_PySymtable_Build, _PySymtable_BuildObject, _PySymtable_Free,
_PySymtable_Lookup, _PySys_AddAuditHook, _PySys_AddWarnOption,
_PySys_AddWarnOptionUnicode, _PySys_AddXOption, _PySys_Audit,
_PySys_FormatStderr, _PySys_FormatStdout, _PySys_GetObject,
_PySys_GetXOptions, _PySys_HasWarnOptions, _PySys_ResetWarnOptions,
_PySys_SetArgv, _PySys_SetArgvEx, _PySys_SetObject, _PySys_SetPath,
_PySys_WriteStderr, _PySys_WriteStdout, _PyThreadState_Clear,
_PyThreadState_Delete, _PyThreadState_DeleteCurrent, _PyThreadState_Get,
_PyThreadState_GetDict, _PyThreadState_GetFrame, _PyThreadState_GetID,
_PyThreadState_GetInterpreter, _PyThreadState_New, _PyThreadState_Next,
_PyThreadState_SetAsyncExc, _PyThreadState_Swap, _PyThread_GetInfo,
_PyThread_ReInitTLS, _PyThread_acquire_lock, _PyThread_acquire_lock_timed,
_PyThread_allocate_lock, _PyThread_create_key, _PyThread_delete_key,
_PyThread_delete_key_value, _PyThread_exit_thread, _PyThread_free_lock,
_PyThread_get_key_value, _PyThread_get_stacksize, _PyThread_get_thread_ident,
_PyThread_get_thread_native_id, _PyThread_init_thread, _PyThread_release_lock,
_PyThread_set_key_value, _PyThread_set_stacksize, _PyThread_start_new_thread,
_PyThread_tss_alloc, _PyThread_tss_create, _PyThread_tss_delete,
_PyThread_tss_free, _PyThread_tss_get, _PyThread_tss_is_created,
_PyThread_tss_set, _PyToken_OneChar, _PyToken_ThreeChars,
_PyToken_TwoChars, _PyTraceBack_Here, _PyTraceBack_Print,
_PyTraceBack_Type, _PyTraceMalloc_Track, _PyTraceMalloc_Untrack,
_PyTupleIter_Type, _PyTuple_GetItem, _PyTuple_GetSlice, _PyTuple_New,
_PyTuple_Pack, _PyTuple_SetItem, _PyTuple_Size, _PyTuple_Type,
_PyType_ClearCache, _PyType_FromModuleAndSpec, _PyType_FromSpec,
_PyType_FromSpecWithBases, _PyType_GenericAlloc, _PyType_GenericNew,
_PyType_GetFlags, _PyType_GetModule, _PyType_GetModuleState,
_PyType_GetSlot, _PyType_IsSubtype, _PyType_Modified, _PyType_Ready,
_PyType_Type, _PyUnicodeDecodeError_Create, _PyUnicodeDecodeError_GetEncoding,
_PyUnicodeDecodeError_GetEnd, _PyUnicodeDecodeError_GetObject,
_PyUnicodeDecodeError_GetReason, _PyUnicodeDecodeError_GetStart,
_PyUnicodeDecodeError_SetEnd, _PyUnicodeDecodeError_SetReason,
_PyUnicodeDecodeError_SetStart, _PyUnicodeEncodeError_Create,
_PyUnicodeEncodeError_GetEncoding, _PyUnicodeEncodeError_GetEnd,
_PyUnicodeEncodeError_GetObject, _PyUnicodeEncodeError_GetReason,
_PyUnicodeEncodeError_GetStart, _PyUnicodeEncodeError_SetEnd,
_PyUnicodeEncodeError_SetReason, _PyUnicodeEncodeError_SetStart,
_PyUnicodeIter_Type, _PyUnicodeTranslateError_Create, _PyUnicodeTranslateError_GetEnd,
_PyUnicodeTranslateError_GetObject, _PyUnicodeTranslateError_GetReason,
_PyUnicodeTranslateError_GetStart, _PyUnicodeTranslateError_SetEnd,
_PyUnicodeTranslateError_SetReason, _PyUnicodeTranslateError_SetStart,
_PyUnicode_Append, _PyUnicode_AppendAndDel, _PyUnicode_AsASCIIString,
_PyUnicode_AsCharmapString, _PyUnicode_AsDecodedObject, _PyUnicode_AsDecodedUnicode,
_PyUnicode_AsEncodedObject, _PyUnicode_AsEncodedString, _PyUnicode_AsEncodedUnicode,
_PyUnicode_AsLatin1String, _PyUnicode_AsRawUnicodeEscapeString,
_PyUnicode_AsUCS4, _PyUnicode_AsUCS4Copy, _PyUnicode_AsUTF16String,
_PyUnicode_AsUTF32String, _PyUnicode_AsUTF8, _PyUnicode_AsUTF8AndSize,
_PyUnicode_AsUTF8String, _PyUnicode_AsUnicode, _PyUnicode_AsUnicodeAndSize,
_PyUnicode_AsUnicodeCopy, _PyUnicode_AsUnicodeEscapeString,
_PyUnicode_AsWideChar, _PyUnicode_AsWideCharString, _PyUnicode_BuildEncodingMap,
_PyUnicode_Compare, _PyUnicode_CompareWithASCIIString, _PyUnicode_Concat,
_PyUnicode_Contains, _PyUnicode_CopyCharacters, _PyUnicode_Count,
_PyUnicode_Decode, _PyUnicode_DecodeASCII, _PyUnicode_DecodeCharmap,
_PyUnicode_DecodeFSDefault, _PyUnicode_DecodeFSDefaultAndSize,
_PyUnicode_DecodeLatin1, _PyUnicode_DecodeLocale, _PyUnicode_DecodeLocaleAndSize,
_PyUnicode_DecodeRawUnicodeEscape, _PyUnicode_DecodeUTF16,
_PyUnicode_DecodeUTF16Stateful, _PyUnicode_DecodeUTF32, _PyUnicode_DecodeUTF32Stateful,
_PyUnicode_DecodeUTF7, _PyUnicode_DecodeUTF7Stateful, _PyUnicode_DecodeUTF8,
_PyUnicode_DecodeUTF8Stateful, _PyUnicode_DecodeUnicodeEscape,
_PyUnicode_Encode, _PyUnicode_EncodeASCII, _PyUnicode_EncodeCharmap,
_PyUnicode_EncodeDecimal, _PyUnicode_EncodeFSDefault, _PyUnicode_EncodeLatin1,
_PyUnicode_EncodeLocale, _PyUnicode_EncodeRawUnicodeEscape,
_PyUnicode_EncodeUTF16, _PyUnicode_EncodeUTF32, _PyUnicode_EncodeUTF7,
_PyUnicode_EncodeUTF8, _PyUnicode_EncodeUnicodeEscape, _PyUnicode_FSConverter,
_PyUnicode_FSDecoder, _PyUnicode_Fill, _PyUnicode_Find, _PyUnicode_FindChar,
_PyUnicode_Format, _PyUnicode_FromEncodedObject, _PyUnicode_FromFormat,
_PyUnicode_FromFormatV, _PyUnicode_FromKindAndData, _PyUnicode_FromObject,
_PyUnicode_FromOrdinal, _PyUnicode_FromString, _PyUnicode_FromStringAndSize,
_PyUnicode_FromUnicode, _PyUnicode_FromWideChar, _PyUnicode_GetDefaultEncoding,
_PyUnicode_GetLength, _PyUnicode_GetMax, _PyUnicode_GetSize,
_PyUnicode_InternFromString, _PyUnicode_InternImmortal, _PyUnicode_InternInPlace,
_PyUnicode_IsIdentifier, _PyUnicode_Join, _PyUnicode_New,
_PyUnicode_Partition, _PyUnicode_RPartition, _PyUnicode_RSplit,
_PyUnicode_ReadChar, _PyUnicode_Replace, _PyUnicode_Resize,
_PyUnicode_RichCompare, _PyUnicode_Split, _PyUnicode_Splitlines,
_PyUnicode_Substring, _PyUnicode_Tailmatch, _PyUnicode_TransformDecimalToASCII,
_PyUnicode_Translate, _PyUnicode_TranslateCharmap, _PyUnicode_Type,
_PyUnicode_WriteChar, _PyVectorcall_Call, _PyWeakref_GetObject,
_PyWeakref_NewProxy, _PyWeakref_NewRef, _PyWideStringList_Append,
_PyWideStringList_Insert, _PyWrapperDescr_Type, _PyWrapper_New,
_PyZip_Type, _Py_AddPendingCall, _Py_AtExit, _Py_BuildValue,
_Py_BytesMain, _Py_BytesWarningFlag, _Py_CompileString, _Py_CompileStringExFlags,
_Py_CompileStringFlags, _Py_CompileStringObject, _Py_DebugFlag,
_Py_DecRef, _Py_DecodeLocale, _Py_DontWriteBytecodeFlag, _Py_EncodeLocale,
_Py_EndInterpreter, _Py_EnterRecursiveCall, _Py_Exit, _Py_ExitStatusException,
_Py_FatalError, _Py_FdIsInteractive, _Py_FileSystemDefaultEncodeErrors,
_Py_FileSystemDefaultEncoding, _Py_Finalize, _Py_FinalizeEx,
_Py_FrozenFlag, _Py_GenericAlias, _Py_GenericAliasType, _Py_GetArgcArgv,
_Py_GetBuildInfo, _Py_GetCompiler, _Py_GetCopyright, _Py_GetExecPrefix,
_Py_GetPath, _Py_GetPlatform, _Py_GetPrefix, _Py_GetProgramFullPath,
_Py_GetProgramName, _Py_GetPythonHome, _Py_GetRecursionLimit,
_Py_GetVersion, _Py_HasFileSystemDefaultEncoding, _Py_HashRandomizationFlag,
_Py_IgnoreEnvironmentFlag, _Py_IncRef, _Py_Initialize, _Py_InitializeEx,
_Py_InitializeFromConfig, _Py_InspectFlag, _Py_InteractiveFlag,
_Py_IsInitialized, _Py_IsolatedFlag, _Py_LeaveRecursiveCall,
_Py_Main, _Py_MakePendingCalls, _Py_NewInterpreter, _Py_NoSiteFlag,
_Py_NoUserSiteDirectory, _Py_OptimizeFlag, _Py_PreInitialize,
_Py_PreInitializeFromArgs, _Py_PreInitializeFromBytesArgs,
_Py_QuietFlag, _Py_ReprEnter, _Py_ReprLeave, _Py_RunMain,
_Py_SetPath, _Py_SetProgramName, _Py_SetPythonHome, _Py_SetRecursionLimit,
_Py_SetStandardStreamEncoding, _Py_SymtableString, _Py_SymtableStringObject,
_Py_UNICODE_strcat, _Py_UNICODE_strchr, _Py_UNICODE_strcmp,
_Py_UNICODE_strcpy, _Py_UNICODE_strlen, _Py_UNICODE_strncmp,
_Py_UNICODE_strncpy, _Py_UNICODE_strrchr, _Py_UTF8Mode, _Py_UnbufferedStdioFlag,
_Py_UniversalNewlineFgets, _Py_VaBuildValue, _Py_VerboseFlag,
_Py_hexdigits, __PyAST_GetDocString, __PyAST_Optimize, __PyAccu_Accumulate,
__PyAccu_Destroy, __PyAccu_Finish, __PyAccu_FinishAsList,
__PyAccu_Init, __PyArg_BadArgument, __PyArg_CheckPositional,
__PyArg_NoKeywords, __PyArg_NoKwnames, __PyArg_NoPositional,
__PyArg_ParseStack, __PyArg_ParseStackAndKeywords, __PyArg_ParseStackAndKeywords_SizeT,
__PyArg_ParseStack_SizeT, __PyArg_ParseTupleAndKeywordsFast,
__PyArg_ParseTupleAndKeywordsFast_SizeT, __PyArg_ParseTupleAndKeywords_SizeT,
__PyArg_ParseTuple_SizeT, __PyArg_Parse_SizeT, __PyArg_UnpackKeywords,
__PyArg_UnpackStack, __PyArg_VaParseTupleAndKeywordsFast,
__PyArg_VaParseTupleAndKeywordsFast_SizeT, __PyArg_VaParseTupleAndKeywords_SizeT,
__PyArg_VaParse_SizeT, __PyArgv_AsWstrList, __PyAsyncGenASend_Type,
__PyAsyncGenAThrow_Type, __PyAsyncGenWrappedValue_Type, __PyByteArray_empty_string,
__PyBytesIOBuffer_Type, __PyBytesWriter_Alloc, __PyBytesWriter_Dealloc,
__PyBytesWriter_Finish, __PyBytesWriter_Init, __PyBytesWriter_Prepare,
__PyBytesWriter_Resize, __PyBytesWriter_WriteBytes, __PyBytes_DecodeEscape,
__PyBytes_FormatEx, __PyBytes_FromHex, __PyBytes_Join, __PyBytes_Resize,
__PyCode_CheckLineNumber, __PyCode_ConstantKey, __PyCode_GetExtra,
__PyCode_SetExtra, __PyCodecInfo_GetIncrementalDecoder, __PyCodecInfo_GetIncrementalEncoder,
__PyCodec_DecodeText, __PyCodec_EncodeText, __PyCodec_Forget,
__PyCodec_Lookup, __PyCodec_LookupTextEncoding, __PyComplex_FormatAdvancedWriter,
__PyConfig_InitCompatConfig, __PyContext_NewHamtForTests,
__PyCoroWrapper_Type, __PyCrossInterpreterData_Lookup, __PyCrossInterpreterData_NewObject,
__PyCrossInterpreterData_RegisterClass, __PyCrossInterpreterData_Release,
__PyDebugAllocatorStats, __PyDictView_Intersect, __PyDictView_New,
__PyDict_CheckConsistency, __PyDict_Contains, __PyDict_DebugMallocStats,
__PyDict_DelItemId, __PyDict_DelItemIf, __PyDict_DelItem_KnownHash,
__PyDict_GetItemId, __PyDict_GetItemIdWithError, __PyDict_GetItemStringWithError,
__PyDict_GetItem_KnownHash, __PyDict_HasOnlyStringKeys, __PyDict_MaybeUntrack,
__PyDict_MergeEx, __PyDict_NewPresized, __PyDict_Next, __PyDict_Pop,
__PyDict_SetItemId, __PyDict_SetItem_KnownHash, __PyDict_SizeOf,
__PyErr_BadInternalCall, __PyErr_ChainExceptions, __PyErr_ChainStackItem,
__PyErr_CheckSignals, __PyErr_CheckSignalsTstate, __PyErr_Clear,
__PyErr_Display, __PyErr_ExceptionMatches, __PyErr_Fetch,
__PyErr_Format, __PyErr_FormatFromCause, __PyErr_FormatFromCauseTstate,
__PyErr_GetExcInfo, __PyErr_GetTopmostException, __PyErr_NoMemory,
__PyErr_NormalizeException, __PyErr_Print, __PyErr_Restore,
__PyErr_SetKeyError, __PyErr_SetNone, __PyErr_SetObject, __PyErr_SetString,
__PyErr_TrySetFromCause, __PyErr_WriteUnraisableMsg, __PyEval_AddPendingCall,
__PyEval_CallTracing, __PyEval_EvalCodeWithName, __PyEval_EvalFrameDefault,
__PyEval_GetAsyncGenFinalizer, __PyEval_GetAsyncGenFirstiter,
__PyEval_GetBuiltinId, __PyEval_GetCoroutineOriginTrackingDepth,
__PyEval_GetSwitchInterval, __PyEval_RequestCodeExtraIndex,
__PyEval_SetAsyncGenFinalizer, __PyEval_SetAsyncGenFirstiter,
__PyEval_SetCoroutineOriginTrackingDepth, __PyEval_SetProfile,
__PyEval_SetSwitchInterval, __PyEval_SetTrace, __PyEval_SignalAsyncExc,
__PyEval_SignalReceived, __PyEval_SliceIndex, __PyEval_SliceIndexNotNone,
__PyFloat_DebugMallocStats, __PyFloat_FormatAdvancedWriter,
__PyFloat_Pack2, __PyFloat_Pack4, __PyFloat_Pack8, __PyFloat_Unpack2,
__PyFloat_Unpack4, __PyFloat_Unpack8, __PyFrame_DebugMallocStats,
__PyFunction_Vectorcall, __PyGC_CollectIfEnabled, __PyGC_CollectNoFail,
__PyGC_InitState, __PyGILState_GetInterpreterStateUnsafe,
__PyGILState_Reinit, __PyGen_FetchStopIterationValue, __PyGen_Finalize,
__PyGen_Send, __PyGen_SetStopIterationValue, __PyHamtItems_Type,
__PyHamtKeys_Type, __PyHamtValues_Type, __PyHamt_ArrayNode_Type,
__PyHamt_BitmapNode_Type, __PyHamt_CollisionNode_Type, __PyHamt_Type,
__PyImport_AcquireLock, __PyImport_FindExtensionObject, __PyImport_FixupBuiltin,
__PyImport_FixupExtensionObject, __PyImport_GetModuleId, __PyImport_IsInitialized,
__PyImport_ReleaseLock, __PyImport_SetModule, __PyImport_SetModuleString,
__PyInterpreterID_LookUp, __PyInterpreterID_New, __PyInterpreterID_Type,
__PyInterpreterState_DeleteExceptMain, __PyInterpreterState_Enable,
__PyInterpreterState_GetConfig, __PyInterpreterState_GetEvalFrameFunc,
__PyInterpreterState_GetIDObject, __PyInterpreterState_GetMainModule,
__PyInterpreterState_IDDecref, __PyInterpreterState_IDIncref,
__PyInterpreterState_IDInitref, __PyInterpreterState_LookUpID,
__PyInterpreterState_RequireIDRef, __PyInterpreterState_RequiresIDRef,
__PyInterpreterState_SetEvalFrameFunc, __PyList_DebugMallocStats,
__PyList_Extend, __PyLong_AsByteArray, __PyLong_AsInt, __PyLong_AsTime_t,
__PyLong_Copy, __PyLong_DigitValue, __PyLong_DivmodNear, __PyLong_Format,
__PyLong_FormatAdvancedWriter, __PyLong_FormatBytesWriter,
__PyLong_FormatWriter, __PyLong_Frexp, __PyLong_FromByteArray,
__PyLong_FromBytes, __PyLong_FromGid, __PyLong_FromNbIndexOrNbInt,
__PyLong_FromNbInt, __PyLong_FromTime_t, __PyLong_FromUid,
__PyLong_GCD, __PyLong_Lshift, __PyLong_New, __PyLong_NumBits,
__PyLong_One, __PyLong_Rshift, __PyLong_Sign, __PyLong_Size_t_Converter,
__PyLong_UnsignedInt_Converter, __PyLong_UnsignedLongLong_Converter,
__PyLong_UnsignedLong_Converter, __PyLong_UnsignedShort_Converter,
__PyLong_Zero, __PyManagedBuffer_Type, __PyMem_GetAllocatorName,
__PyMem_GetCurrentAllocatorName, __PyMem_RawStrdup, __PyMem_RawWcsdup,
__PyMem_SetDefaultAllocator, __PyMem_SetupAllocators, __PyMem_Strdup,
__PyMethodWrapper_Type, __PyModuleSpec_IsInitializing, __PyModule_Clear,
__PyModule_ClearDict, __PyModule_CreateInitialized, __PyNamespace_New,
__PyNamespace_Type, __PyNode_SizeOf, __PyNone_Type, __PyNotImplemented_Type,
__PyOS_InterruptOccurred, __PyOS_IsMainThread, __PyOS_ReadlineTState,
__PyOS_URandom, __PyOS_URandomNonblock, __PyObject_AssertFailed,
__PyObject_Call, __PyObject_CallFunction_SizeT, __PyObject_CallMethodId,
__PyObject_CallMethodIdObjArgs, __PyObject_CallMethodId_SizeT,
__PyObject_CallMethod_SizeT, __PyObject_Call_Prepend, __PyObject_CheckConsistency,
__PyObject_CheckCrossInterpreterData, __PyObject_DebugMallocStats,
__PyObject_DebugTypeStats, __PyObject_Dump, __PyObject_FastCallDictTstate,
__PyObject_FunctionStr, __PyObject_GC_Calloc, __PyObject_GC_Malloc,
__PyObject_GC_New, __PyObject_GC_NewVar, __PyObject_GC_Resize,
__PyObject_GenericGetAttrWithDict, __PyObject_GenericSetAttrWithDict,
__PyObject_GetAttrId, __PyObject_GetCrossInterpreterData,
__PyObject_GetDictPtr, __PyObject_GetMethod, __PyObject_HasAttrId,
__PyObject_HasLen, __PyObject_IsAbstract, __PyObject_IsFreed,
__PyObject_LookupAttr, __PyObject_LookupAttrId, __PyObject_LookupSpecial,
__PyObject_MakeTpCall, __PyObject_New, __PyObject_NewVar,
__PyObject_NextNotImplemented, __PyObject_RealIsInstance,
__PyObject_RealIsSubclass, __PyObject_SetAttrId, __PyParser_Grammar,
__PyParser_TokenNames, __PyPreConfig_InitCompatConfig, __PyRuntime,
__PyRuntimeState_Fini, __PyRuntimeState_Init, __PyRuntimeState_ReInitThreads,
__PyRuntime_Finalize, __PyRuntime_Initialize, __PySequence_BytesToCharpArray,
__PySequence_IterSearch, __PySet_Dummy, __PySet_NextEntry,
__PySet_Update, __PySignal_AfterFork, __PySlice_FromIndices,
__PySlice_GetLongIndices, __PyStack_AsDict, __PyState_AddModule,
__PySys_GetObjectId, __PySys_GetSizeOf, __PySys_SetObjectId,
__PyThreadState_DeleteCurrent, __PyThreadState_DeleteExcept,
__PyThreadState_GetDict, __PyThreadState_Init, __PyThreadState_Prealloc,
__PyThreadState_Swap, __PyThreadState_UncheckedGet, __PyThread_CurrentFrames,
__PyThread_at_fork_reinit, __PyTime_AsMicroseconds, __PyTime_AsMilliseconds,
__PyTime_AsNanosecondsObject, __PyTime_AsSecondsDouble, __PyTime_AsTimespec,
__PyTime_AsTimeval, __PyTime_AsTimevalTime_t, __PyTime_AsTimeval_noraise,
__PyTime_FromMillisecondsObject, __PyTime_FromNanoseconds,
__PyTime_FromNanosecondsObject, __PyTime_FromSeconds, __PyTime_FromSecondsObject,
__PyTime_FromTimespec, __PyTime_FromTimeval, __PyTime_GetMonotonicClock,
__PyTime_GetMonotonicClockWithInfo, __PyTime_GetPerfCounter,
__PyTime_GetPerfCounterWithInfo, __PyTime_GetSystemClock,
__PyTime_GetSystemClockWithInfo, __PyTime_Init, __PyTime_MulDiv,
__PyTime_ObjectToTime_t, __PyTime_ObjectToTimespec, __PyTime_ObjectToTimeval,
__PyTime_gmtime, __PyTime_localtime, __PyTraceMalloc_GetTraceback,
__PyTraceMalloc_NewReference, __PyTraceback_Add, __PyTrash_begin,
__PyTrash_deposit_object, __PyTrash_destroy_chain, __PyTrash_end,
__PyTrash_thread_deposit_object, __PyTrash_thread_destroy_chain,
__PyTuple_DebugMallocStats, __PyTuple_MaybeUntrack, __PyTuple_Resize,
__PyType_CalculateMetaclass, __PyType_CheckConsistency, __PyType_GetDocFromInternalDoc,
__PyType_GetTextSignatureFromInternalDoc, __PyType_Lookup,
__PyType_LookupId, __PyType_Name, __PyUnicodeTranslateError_Create,
__PyUnicodeWriter_Dealloc, __PyUnicodeWriter_Finish, __PyUnicodeWriter_Init,
__PyUnicodeWriter_PrepareInternal, __PyUnicodeWriter_PrepareKindInternal,
__PyUnicodeWriter_WriteASCIIString, __PyUnicodeWriter_WriteChar,
__PyUnicodeWriter_WriteLatin1String, __PyUnicodeWriter_WriteStr,
__PyUnicodeWriter_WriteSubstring, __PyUnicode_AsASCIIString,
__PyUnicode_AsLatin1String, __PyUnicode_AsUTF8String, __PyUnicode_AsUnicode,
__PyUnicode_CheckConsistency, __PyUnicode_Copy, __PyUnicode_DecodeUnicodeEscape,
__PyUnicode_EQ, __PyUnicode_EncodeCharmap, __PyUnicode_EncodeUTF16,
__PyUnicode_EncodeUTF32, __PyUnicode_EncodeUTF7, __PyUnicode_EqualToASCIIId,
__PyUnicode_EqualToASCIIString, __PyUnicode_FastCopyCharacters,
__PyUnicode_FastFill, __PyUnicode_FindMaxChar, __PyUnicode_FormatAdvancedWriter,
__PyUnicode_FormatLong, __PyUnicode_FromASCII, __PyUnicode_FromId,
__PyUnicode_InsertThousandsGrouping, __PyUnicode_IsAlpha,
__PyUnicode_IsCaseIgnorable, __PyUnicode_IsCased, __PyUnicode_IsDecimalDigit,
__PyUnicode_IsDigit, __PyUnicode_IsLinebreak, __PyUnicode_IsLowercase,
__PyUnicode_IsNumeric, __PyUnicode_IsPrintable, __PyUnicode_IsTitlecase,
__PyUnicode_IsUppercase, __PyUnicode_IsWhitespace, __PyUnicode_IsXidContinue,
__PyUnicode_IsXidStart, __PyUnicode_JoinArray, __PyUnicode_Ready,
__PyUnicode_ScanIdentifier, __PyUnicode_ToDecimalDigit, __PyUnicode_ToDigit,
__PyUnicode_ToFoldedFull, __PyUnicode_ToLowerFull, __PyUnicode_ToLowercase,
__PyUnicode_ToNumeric, __PyUnicode_ToTitleFull, __PyUnicode_ToTitlecase,
__PyUnicode_ToUpperFull, __PyUnicode_ToUppercase, __PyUnicode_TransformDecimalAndSpaceToASCII,
__PyUnicode_XStrip, __PyWarnings_Init, __PyWeakref_CallableProxyType,
__PyWeakref_ClearRef, __PyWeakref_GetWeakrefCount, __PyWeakref_ProxyType,
__PyWeakref_RefType, __PyWideStringList_AsList, __PyWideStringList_Clear,
__PyWideStringList_Copy, __PyWideStringList_Extend, __Py_BreakPoint,
__Py_BuildValue_SizeT, __Py_CheckFunctionResult, __Py_CheckRecursionLimit,
__Py_CheckRecursiveCall, __Py_ClearArgcArgv, __Py_ClearStandardStreamEncoding,
__Py_CoerceLegacyLocale, __Py_Dealloc, __Py_DecodeLocaleEx,
__Py_DecodeUTF8Ex, __Py_DecodeUTF8_surrogateescape, __Py_DisplaySourceLine,
__Py_EllipsisObject, __Py_EncodeLocaleEx, __Py_EncodeLocaleRaw,
__Py_EncodeUTF8Ex, __Py_FalseStruct, __Py_FatalErrorFormat,
__Py_FatalErrorFunc, __Py_FatalError_TstateNULL, __Py_FreeCharPArray,
__Py_GetAllocatedBlocks, __Py_GetConfig, __Py_GetConfigsAsDict,
__Py_GetEnv, __Py_GetErrorHandler, __Py_GetForceASCII, __Py_GetLocaleconvNumeric,
__Py_Gid_Converter, __Py_HandleSystemExit, __Py_HashBytes,
__Py_HashDouble, __Py_HashPointer, __Py_HashPointerRaw, __Py_HashSecret,
__Py_InitializeMain, __Py_IsCoreInitialized, __Py_IsFinalizing,
__Py_IsLocaleCoercionTarget, __Py_LegacyLocaleDetected, __Py_Mangle,
__Py_NewInterpreter, __Py_NewReference, __Py_NoneStruct, __Py_NotImplementedStruct,
__Py_PackageContext, __Py_PreInitializeFromConfig, __Py_PreInitializeFromPyArgv,
__Py_PyAtExit, __Py_ResetForceASCII, __Py_RestoreSignals,
__Py_SetLocaleFromEnv, __Py_SetProgramFullPath, __Py_Sigset_Converter,
__Py_SourceAsString, __Py_SwappedOp, __Py_SymtableStringObjectFlags,
__Py_TrueStruct, __Py_Uid_Converter, __Py_UnhandledKeyboardInterrupt,
__Py_VaBuildStack, __Py_VaBuildStack_SizeT, __Py_VaBuildValue_SizeT,
__Py_abspath, __Py_add_one_to_index_C, __Py_add_one_to_index_F,
__Py_ascii_whitespace, __Py_bit_length, __Py_c_abs, __Py_c_diff,
__Py_c_neg, __Py_c_pow, __Py_c_prod, __Py_c_quot, __Py_c_sum,
__Py_convert_optional_to_ssize_t, __Py_ctype_table, __Py_ctype_tolower,
__Py_ctype_toupper, __Py_device_encoding, __Py_dg_dtoa, __Py_dg_freedtoa,
__Py_dg_infinity, __Py_dg_stdnan, __Py_dg_strtod, __Py_dup,
__Py_fopen, __Py_fopen_obj, __Py_fstat, __Py_fstat_noraise,
__Py_get_blocking, __Py_get_env_flag, __Py_get_inheritable,
__Py_get_xoption, __Py_gitidentifier, __Py_gitversion, __Py_hashtable_clear,
__Py_hashtable_compare_direct, __Py_hashtable_destroy, __Py_hashtable_foreach,
__Py_hashtable_get, __Py_hashtable_hash_ptr, __Py_hashtable_new,
__Py_hashtable_new_full, __Py_hashtable_set, __Py_hashtable_size,
__Py_hashtable_steal, __Py_isabs, __Py_open, __Py_open_noraise,
__Py_parse_inf_or_nan, __Py_path_config, __Py_read, __Py_set_blocking,
__Py_set_inheritable, __Py_set_inheritable_async_safe, __Py_stat,
__Py_str_to_int, __Py_strhex, __Py_strhex_bytes, __Py_strhex_bytes_with_sep,
__Py_strhex_with_sep, __Py_string_to_number_with_underscores,
__Py_tracemalloc_config, __Py_wfopen, __Py_wgetcwd, __Py_wreadlink,
__Py_wrealpath, __Py_write, __Py_write_noraise ]
...
+97 -26
View File
@@ -24,8 +24,8 @@ include ../../allmake.mak
#----------------------------------------------------------------------
# default goals
.PHONY: configs modules pyfiles deployed_modules idapython_modules api_contents pydoc_injections pyqt sip bins public_tree test_idc docs
all: configs modules pyfiles deployed_modules idapython_modules api_contents pydoc_injections pyqt sip bins # public_tree test_idc docs
.PHONY: configs modules pyfiles deployed_modules idapython_modules api_contents pydoc_injections pyqt sip bins public_tree test_idc docs tbd examples_index
all: configs modules pyfiles deployed_modules idapython_modules api_contents pydoc_injections pyqt sip bins examples_index # public_tree test_idc docs
ifeq ($(OUT_OF_TREE_BUILD),)
BINS += $(IDAPYSWITCH)
@@ -127,6 +127,17 @@ else
endif
endif
#----------------------------------------------------------------------
ifdef __APPLE_SILICON__
# set up a stub .tbd library to link against, see tbd.readme
TBD_FILE = libpython$(PYTHON_VERSION_MAJOR).tbd
# note: this path must be compatible with -L$(R) -lpython(2|3) in pyplg.mak
TBD_MODULE_DEP = $(R)$(TBD_FILE)
# idapyswitch must be told that we're working with Python2
ifeq ($(PYTHON_VERSION_MAJOR),2)
TBD_IDAPYSWITCH_ARGS = --use-python2
endif
endif
#----------------------------------------------------------------------
# we explicitly added our module targets
@@ -143,7 +154,7 @@ include ../pyplg.mak
#----------------------------------------------------------------------
PYTHON_OBJS += $(F)idapython$(O)
$(MODULE): MODULE_OBJS += $(PYTHON_OBJS)
$(MODULE): $(PYTHON_OBJS) $(IDAPYSWITCH_MODULE_DEP)
$(MODULE): $(PYTHON_OBJS) $(IDAPYSWITCH_MODULE_DEP) $(TBD_MODULE_DEP)
ifdef __NT__
$(MODULE): LDFLAGS += /DEF:$(IDAPYTHON_IMPLIB_DEF) /IMPLIB:$(IDAPYTHON_IMPLIB_PATH)
endif
@@ -177,6 +188,7 @@ ifdef DO_IDAMAKE_SIMPLIFY
QUPDATE_SDK = @echo $(call qcolor,update_sdk) $< && #
QSPLIT_HEXRAYS_TEMPLATES = @echo $(call qcolor,split_hexrays_templates) $< && #
QPYDOC_INJECTIONS = @echo $(call qcolor,check_injections) $@ && #
QGEN_EXAMPLES_INDEX = @echo $(call qcolor,gen_examples_index) $@ && #
endif
#----------------------------------------------------------------------
@@ -226,7 +238,7 @@ ifeq ($(OUT_OF_TREE_BUILD),)
SDK_SOURCES+=$(IDA_INCLUDE)/hexrays.hpp
endif
SDK_SOURCES+=$(IDA_INCLUDE)/lumina.hpp
SDK_SOURCES+=$(IDA_INCLUDE)/dirtree.hpp
SDK_SOURCES+=$(IDA_INCLUDE)/srclang.hpp
else
SDK_SOURCES=$(wildcard $(IDA_INCLUDE)/*.h) $(wildcard $(IDA_INCLUDE)/*.hpp)
endif
@@ -273,6 +285,7 @@ MODULES_NAMES += bitrange
MODULES_NAMES += bytes
MODULES_NAMES += dbg
MODULES_NAMES += diskio
MODULES_NAMES += dirtree
MODULES_NAMES += entry
MODULES_NAMES += enum
MODULES_NAMES += expr
@@ -287,15 +300,12 @@ MODULES_NAMES += idaapi
MODULES_NAMES += idc
MODULES_NAMES += idd
MODULES_NAMES += idp
MODULES_NAMES += ieee
MODULES_NAMES += kernwin
MODULES_NAMES += lines
MODULES_NAMES += loader
ifdef TESTABLE_BUILD
MODULES_NAMES += lumina
# when dirtree.hpp makes it into the SDK, add all relevant scripts
# that are currently in tests/ui/, into plugins/idapython/examples/.
# Grep for 'dirtree' and 'dirspec' to spot those.
MODULES_NAMES += dirtree
endif
MODULES_NAMES += moves
MODULES_NAMES += nalt
@@ -309,6 +319,9 @@ MODULES_NAMES += registry
MODULES_NAMES += search
MODULES_NAMES += segment
MODULES_NAMES += segregs
ifdef TESTABLE_BUILD
MODULES_NAMES += srclang
endif
MODULES_NAMES += strlist
MODULES_NAMES += struct
MODULES_NAMES += tryblks
@@ -420,6 +433,18 @@ ifeq ($(OUT_OF_TREE_BUILD),)
$(Q)$(CP) $? $@
DEST_SIP += $(DEST_SIP39_PYDLL) $(DEST_SIP39_PYI)
# sip for Python [3.10, ...
DEST_SIP310_DIR:=$(DEST_PYQT_DIR)/python_3.10
$(DEST_SIP310_DIR):
-$(Q)if [ ! -d "$(DEST_SIP310_DIR)" ] ; then mkdir -p 2>/dev/null $(DEST_SIP310_DIR) ; fi
DEST_SIP310_PYDLL:=$(DEST_SIP310_DIR)/$(SIP_PYDLL_FNAME)
DEST_SIP310_PYI:=$(DEST_SIP310_DIR)/$(SIP_PYI_FNAME)
$(DEST_SIP310_PYDLL): $(wildcard $(SIP310_TREE)/lib/python*/PyQt5/$(SIP_PYDLL_FNAME)) | $(DEST_SIP310_DIR)
$(Q)$(CP) $? $@
$(DEST_SIP310_PYI): $(wildcard $(SIP310_TREE)/lib/python*/PyQt5/$(SIP_PYI_FNAME)) | $(DEST_SIP310_DIR)
$(Q)$(CP) $? $@
DEST_SIP += $(DEST_SIP310_PYDLL) $(DEST_SIP310_PYI)
else
# sip for Python 2.7
DEST_SIP27_DIR:=$(DEST_PYQT_DIR)
@@ -680,16 +705,14 @@ SWIG_IFACE_dbg=idd
SWIG_IFACE_frame=range
SWIG_IFACE_funcs=range
SWIG_IFACE_gdl=range
SWIG_IFACE_hexrays=pro typeinf xref
SWIG_IFACE_graph=gdl
SWIG_IFACE_hexrays=pro typeinf xref gdl
SWIG_IFACE_idd=range
SWIG_IFACE_idp=bitrange
SWIG_IFACE_segment=range
SWIG_IFACE_segregs=range
SWIG_IFACE_typeinf=idp
SWIG_IFACE_tryblks=range
# ifdef TESTABLE_BUILD
# SWIG_IFACE_kernwin=dirtree
# endif
MODULE_LIFECYCLE_bytes=--lifecycle-aware
MODULE_LIFECYCLE_hexrays=--lifecycle-aware
@@ -806,7 +829,7 @@ endif
# See Python's dynload_win.c:GetPythonImport() for more details.
$(_IDA_X_SO): STDLIBS += $(LINKIDAPYTHON)
$(_IDA_X_SO): LDFLAGS += $(PYTHON_LDFLAGS) $(PYTHON_LDFLAGS_RPATH_MODULE) $(OUTMAP)$(F)$(@F).map
$(F)_ida_%$(PYDLL_EXT): $(F)%$(O) $(MODULE) $(IDAPYTHON_IMPLIB_DEF) $(IDAPYSWITCH_MODULE_DEP)
$(F)_ida_%$(PYDLL_EXT): $(F)%$(O) $(MODULE) $(IDAPYTHON_IMPLIB_DEF) $(IDAPYSWITCH_MODULE_DEP) $(TBD_MODULE_DEP)
$(call link_dll, $<, $(LINKIDA))
ifdef __NT__
$(Q)$(RM) $(@:$(PYDLL_EXT)=.exp) $(@:$(PYDLL_EXT)=.lib)
@@ -863,7 +886,7 @@ endif
PYDOC_INJECTIONS_IDAT_CMD=$(USE_PYTHON2_ENVVAR) $(IDAT_CMD) $(BATCH_SWITCH) "-OIDAPython:AUTOIMPORT_COMPAT_IDA695=NO" -S"$< $@ $(ST_WRAP) $(DUMPDOC_IS_64)" -t -L$(F)dumpdoc.log >/dev/null
pydoc_injections: $(ST_PYDOC_INJECTIONS)
$(ST_PYDOC_INJECTIONS): tools/dumpdoc.py $(IDAPYTHON_MODULES) $(PYTHON_BINARY_MODULES)
ifeq ($(or $(__CODE_CHECKER__),$(NO_CMP_API),$(__ASAN__),$(IDAHOME)),)
ifeq ($(or $(__CODE_CHECKER__),$(NO_CMP_API),$(__ASAN__),$(IDAHOME),$(DEMO_OR_FREE)),)
$(QPYDOC_INJECTIONS)$(PYDOC_INJECTIONS_IDAT_CMD) || \
(echo "Command \"$(PYDOC_INJECTIONS_IDAT_CMD)\" failed. Check \"$(F)dumpdoc.log\" for details." && false)
$(Q)(diff -w $(PYDOC_INJECTIONS) $(ST_PYDOC_INJECTIONS)) > /dev/null || \
@@ -889,8 +912,7 @@ endif
# the demo version of ida does not have the -B command line option
ifeq ($(OUT_OF_TREE_BUILD),)
ISDEMO=$(shell grep "define DEMO$$" $(IDA_INCLUDE)/commerc.hpp)
ifeq ($(ISDEMO),)
ifndef DEMO_OR_FREE
BATCH_SWITCH=-B
endif
endif
@@ -938,6 +960,17 @@ ifdef __NT__
endif
$(R)idapyswitch$(B): $(call dumb_target, pro, $(IDAPYSWITCH_OBJS))
#----------------------------------------------------------------------
ifdef __APPLE_SILICON__
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)
$(Q)$(CP) $< $@
cd $(R) && $(IDAPYSWITCH) $(TBD_IDAPYSWITCH_ARGS) --force-path $(shell $(PYTHON)-config --prefix)/Python
else
tbd: ;
endif
#----------------------------------------------------------------------
# the 'echo_modules' target must be called explicitly
# Note: used by ida/build/pkgbin.py
@@ -948,14 +981,56 @@ echo_modules:
clean::
rm -rf obj/
ifdef __CODE_CHECKER__
examples_index: ;
else
EXAMPLES := $(wildcard examples/**/*.py)
GEN_EXAMPLES_TOOL := tools/gen_examples_index.py
ST_EXAMPLES_INDEX_HTML := $(F)examples/index.html
ST_EXAMPLES_INDEX_MD := $(F)examples/index.md
define make-examples-index-rules
$(eval EXAMPLES_INDEX := examples/index.$(1))
$(eval ST_EXAMPLES_INDEX := $(2))
$(eval EXAMPLES_TEMPLATE := tools/examples_index_template.$(1))
.PRECIOUS: $(ST_EXAMPLES_INDEX)
$(eval EXAMPLES_INDEX_CMD := $(PYTHON) $(GEN_EXAMPLES_TOOL) \
-t $(EXAMPLES_TEMPLATE) \
-e examples \
-o $(ST_EXAMPLES_INDEX) \
)
$(ST_EXAMPLES_INDEX): $(GEN_EXAMPLES_TOOL) $(EXAMPLES_TEMPLATE) $(EXAMPLES)
-$(Q)if [ ! -d "$(F)examples" ] ; then mkdir -p 2>/dev/null $(F)examples ; fi
$(QGEN_EXAMPLES_INDEX)$(EXAMPLES_INDEX_CMD) \
|| echo FAILED: $(EXAMPLES_INDEX_CMD)
$(Q)diff -w $(EXAMPLES_INDEX) $(ST_EXAMPLES_INDEX) > /dev/null \
|| (echo "EXAMPLES INDEX CHANGED! update $(EXAMPLES_INDEX)" \
&& echo "(New examples: $(ST_EXAMPLES_INDEX)) ***" \
&& diff -U 1 -w $(EXAMPLES_INDEX) $(ST_EXAMPLES_INDEX) \
&& false)
endef
$(eval $(call make-examples-index-rules,html,$(ST_EXAMPLES_INDEX_HTML)))
$(eval $(call make-examples-index-rules,md,$(ST_EXAMPLES_INDEX_MD)))
examples_index: $(ST_EXAMPLES_INDEX_HTML) $(ST_EXAMPLES_INDEX_MD)
endif
$(MODULE): LDFLAGS += $(PYTHON_LDFLAGS) $(PYTHON_LDFLAGS_RPATH_MAIN)
# MAKEDEP dependency list ------------------
$(F)idapyswitch$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)err.h \
$(I)exehdr.h $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \
$(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.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 \
@@ -972,12 +1047,14 @@ $(F)idapyswitch$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
../../ldr/mach-o/h/i386/_types.h \
../../ldr/mach-o/h/i386/eflags.h \
../../ldr/mach-o/h/libkern/OSByteOrder.h \
../../ldr/mach-o/h/libkern/arm/OSByteOrder.h \
../../ldr/mach-o/h/libkern/i386/OSByteOrder.h \
../../ldr/mach-o/h/libkern/i386/_OSByteOrder.h \
../../ldr/mach-o/h/libkern/machine/OSByteOrder.h \
../../ldr/mach-o/h/mach-o/arm/reloc.h \
../../ldr/mach-o/h/mach-o/arm64/reloc.h \
../../ldr/mach-o/h/mach-o/fat.h \
../../ldr/mach-o/h/mach-o/fixup-chains.h \
../../ldr/mach-o/h/mach-o/hppa/reloc.h \
../../ldr/mach-o/h/mach-o/i860/reloc.h \
../../ldr/mach-o/h/mach-o/loader.h \
@@ -1011,19 +1088,13 @@ $(F)idapyswitch$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
../../ldr/mach-o/h/mach/machine/vm_types.h \
../../ldr/mach-o/h/mach/message.h \
../../ldr/mach-o/h/mach/port.h \
../../ldr/mach-o/h/mach/ppc/_structs.h \
../../ldr/mach-o/h/mach/ppc/boolean.h \
../../ldr/mach-o/h/mach/ppc/kern_return.h \
../../ldr/mach-o/h/mach/ppc/thread_status.h \
../../ldr/mach-o/h/mach/ppc/vm_param.h \
../../ldr/mach-o/h/mach/ppc/vm_types.h \
../../ldr/mach-o/h/mach/vm_prot.h \
../../ldr/mach-o/h/mach/vm_types.h \
../../ldr/mach-o/h/ppc/_types.h \
../../ldr/mach-o/h/sys/_posix_availability.h \
../../ldr/mach-o/h/sys/_symbol_aliasing.h \
../../ldr/mach-o/h/sys/cdefs.h \
../../ldr/mach-o/macho_node.h ../../ldr/pe/../idaldr.h \
../../ldr/mach-o/macho_node.h \
../../ldr/mach-o/uncompress.cpp ../../ldr/pe/../idaldr.h \
../../ldr/pe/common.cpp ../../ldr/pe/common.h \
../../ldr/pe/pe.h idapyswitch.cpp idapyswitch_linux.cpp \
idapyswitch_mac.cpp idapyswitch_win.cpp
Binary file not shown.
+3911 -472
View File
File diff suppressed because it is too large Load Diff
+3678 -486
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -515,7 +515,7 @@ class Strings(object):
return self._toseq(True)
def clear_cache(self):
"""Clears the strings list cache"""
"""Clears the string list cache"""
ida_strlist.clear_strlist()
def __init__(self, default_setup = False):
@@ -536,7 +536,7 @@ class Strings(object):
def refresh(self):
"""Refreshes the strings list"""
"""Refreshes the string list"""
ida_strlist.build_strlist()
self.size = ida_strlist.get_strlist_qty()
+2 -2
View File
@@ -509,7 +509,7 @@ static int pyvar_to_idcvar2(
else if ( PyFloat_Check(py_var.o) )
{
double dresult = PyFloat_AsDouble(py_var.o);
ieee_realcvt((void *)&dresult, idc_var->e, 3);
ieee_realcvt((void *)&dresult, &idc_var->e, 3);
idc_var->vtype = VT_FLOAT;
}
// void*
@@ -831,7 +831,7 @@ int ida_export idcvar_to_pyvar(
if ( *py_var == NULL )
{
double x;
if ( processor_t::realcvt(&x, (uint16 *)idc_var.e, (sizeof(x)/2-1)|010) != 1 )
if ( processor_t::realcvt(&x, (fpvalue_t*)&idc_var.e, (sizeof(x)/2-1)|010) != 1 )
INTERR(30160);
*py_var = newref_t(PyFloat_FromDouble(x));
+1
View File
@@ -118,6 +118,7 @@ static const char S_ON_GET_SIZE[] = "OnGetSize";
static const char S_ON_GETTEXT[] = "OnGetText";
static const char S_ON_GET_DIRTREE[] = "OnGetDirTree";
static const char S_ON_INDEX_TO_INODE[] = "OnIndexToInode";
static const char S_ON_INDEX_TO_DIFFPOS[] = "OnIndexToDiffpos";
static const char S_ON_ACTIVATE[] = "OnActivate";
static const char S_ON_DEACTIVATE[] = "OnDeactivate";
static const char S_ON_SELECT[] = "OnSelect";
+2 -4
View File
@@ -332,15 +332,13 @@ static PyObject *py_get_8bit(ea_t ea, uint32 v, int nbit)
//-------------------------------------------------------------------------
/*
#<pydoc>
def bin_search(start_ea, end_ea, image, imask, step, flags):
def bin_search(start_ea, end_ea, data, flags):
"""
Search for a set of bytes in the program
@param start_ea: linear address, start of range to search
@param end_ea: linear address, end of range to search (exclusive)
@param image: the set of bytes to search for
@param imask: a bitfield representing the mask in 'image' (can be None)
@param step: either BIN_SEARCH_FORWARD, or BIN_SEARCH_BACKWARD
@param data: the prepared data to search for (see parse_binpat_str())
@param flags: combination of BIN_SEARCH_* flags
@return: the address of a match, or ida_idaapi.BADADDR if not found
"""
+4 -4
View File
@@ -95,16 +95,16 @@ static bool _to_reg_val(regval_t **out, regval_t *buf, const char *name, PyObjec
static bool convert_float(regval_t *lout, PyObject *in, op_dtype_t)
{
eNE ene;
fpvalue_t fpval;
_cvt_status_t status(PyExc_TypeError, "Expected float value");
double dbl = PyFloat_AsDouble(in);
status.ok = PyErr_Occurred() == NULL;
if ( status.ok )
status.ok = ieee_realcvt(&dbl, ene, 003 /*load double*/) == 0;
status.ok = ieee_realcvt(&dbl, &fpval, 003 /*load double*/) == REAL_ERROR_OK;
if ( !status.ok )
status.failed(PyExc_ValueError).sprnt("Float conversion failed");
if ( status.ok )
lout->set_float(ene);
lout->set_float(fpval);
return status.ok;
}
@@ -256,7 +256,7 @@ static PyObject *_from_reg_val(
case dt_ldbl:
{
double dbl;
status.ok = ieee_realcvt(&dbl, (uint16 *) rv.fval, 013 /*store double*/) == 0;
status.ok = rv.fval.to_double(&dbl) == REAL_ERROR_OK;
if ( status.ok )
res = PyFloat_FromDouble(dbl);
}
+4 -4
View File
@@ -657,10 +657,10 @@ ssize_t py_graph_t::gr_callback(int code, va_list va)
ret = 0;
break;
}
//grcode_changed_graph, // new graph has been set
//grcode_user_size, // calculate node size for user-defined graph
//grcode_user_title, // render node title of a user-defined graph
//grcode_user_draw, // render node of a user-defined graph
// grcode_changed_graph, // new graph has been set
// grcode_user_size, // calculate node size for user-defined graph
// grcode_user_title, // render node title of a user-defined graph
// grcode_user_draw, // render node of a user-defined graph
return ret;
}
+67 -59
View File
@@ -1,18 +1,25 @@
//-------------------------------------------------------------------------
//<code(py_hexrays)>
static bool do_not_check_ctree = false;
#ifdef WITH_HEXRAYS
#define DCLVL_SIMPLE 1
#define DCLVL_FULL 2
static int _debug_hexrays_ctree = -1;
static bool is_debug_hexrays_ctree()
static int is_debug_hexrays_ctree(int level)
{
if ( _debug_hexrays_ctree < 0 )
_debug_hexrays_ctree = qgetenv("IDAPYTHON_DEBUG_HEXRAYS_CTREEE");
return bool(_debug_hexrays_ctree);
{
qstring tmp;
if ( qgetenv("IDAPYTHON_DEBUG_HEXRAYS_CTREE", &tmp) )
_debug_hexrays_ctree = atol(tmp.c_str());
}
return _debug_hexrays_ctree >= level;
}
//-------------------------------------------------------------------------
static void debug_hexrays_ctree(const char *format, ...)
static void debug_hexrays_ctree(int level, const char *format, ...)
{
if ( is_debug_hexrays_ctree() )
if ( is_debug_hexrays_ctree(level) )
{
va_list va;
va_start(va, format);
@@ -27,17 +34,18 @@ static void debug_hexrays_ctree(const char *format, ...)
// - hexrays is unloaded before IDAPython
// - we receive the notification about hexrays going away and:
// + call hexrays_unloading__clear_python_clearable_references();
// + set 'hexdsp = exit_time_dummy_hexdsp' (an NOP hexdsp)
// + set 'do_not_check_ctree = true'
// - we receive 'ui_database_closed', and
// + set 'hexdsp = init_time_dummy_hexdsp'
// + use 'idapython_dummy_hexdsp'
// + set 'do_not_check_ctree = false'
// - IDAPython is unloaded, and during cleanup of the runtime data,
// reachable citem_t's will get destroyed.
// => this means we vill receive 'hx_c*t_cleanup' and 'hx_remitem'
// notifications most likely in the init_time_dummy_hexdsp(),
// rather than in exit_time_dummy_hexdsp() -- which is more than
// just a little counter-intuitive.
static void *idaapi init_time_dummy_hexdsp(int code, ...)
// notifications most likely in the idapython_dummy_hexdsp()
static void *idaapi idapython_dummy_hexdsp(int code, ...)
{
if ( do_not_check_ctree )
return nullptr;
switch ( code )
{
case hx_remitem:
@@ -47,7 +55,7 @@ static void *idaapi init_time_dummy_hexdsp(int code, ...)
case hx_mba_t_term:
case hx_valrng_t_clear:
{
#ifdef _DEBUG
#ifdef TESTABLE_BUILD
va_list va;
va_start(va, code);
void *item = va_arg(va, void *);
@@ -72,7 +80,7 @@ static void *idaapi init_time_dummy_hexdsp(int code, ...)
break;
case hx_remove_optinsn_handler:
{
#ifdef _DEBUG
#ifdef TESTABLE_BUILD
static bool in_removal = false;
if ( !in_removal )
{
@@ -88,7 +96,7 @@ static void *idaapi init_time_dummy_hexdsp(int code, ...)
break;
case hx_remove_optblock_handler:
{
#ifdef _DEBUG
#ifdef TESTABLE_BUILD
static bool in_removal = false;
if ( !in_removal )
{
@@ -110,7 +118,7 @@ static void *idaapi init_time_dummy_hexdsp(int code, ...)
bool install = va_argi(va, bool);
if ( install )
goto BAD_CODE;
#ifdef _DEBUG
#ifdef TESTABLE_BUILD
static bool in_removal = false;
if ( !in_removal )
{
@@ -135,7 +143,11 @@ BAD_CODE:
return NULL;
}
hexdsp_t *hexdsp = init_time_dummy_hexdsp;
hexdsp_t *get_idapython_hexdsp()
{
auto hrdsp = get_hexdsp();
return hrdsp == nullptr ? idapython_dummy_hexdsp : hrdsp;
}
#endif // WITH_HEXRAYS
#define MODULE_NAME "Hex-Rays Decompiler" // Copied from vd/hexrays.cpp
@@ -158,8 +170,8 @@ void delete_qstring_printer_t(qstring_printer_t *qs)
//-------------------------------------------------------------------------
// A set of objects that were created from IDAPython. This is necessary in
// order to delete those objects before the hexrays plugin is unloaded.
// Otherwise, IDAPython will still delete them, but the plugin's 'hexdsp'
// dispatcher function will point to dlclose()'d code.
// Otherwise, IDAPython will still delete them, but the plugin's
// dispatcher function will point to idapython_dummy_hexdsp
enum hx_clearable_type_t
{
hxclr_unknown = 0,
@@ -184,13 +196,28 @@ DECLARE_TYPE_AS_MOVABLE(hx_clearable_t);
typedef qvector<hx_clearable_t> hx_clearables_t;
static hx_clearables_t python_clearables;
//-------------------------------------------------------------------------
static void debug_hexrays_dump_clearable_instances(int level=DCLVL_FULL)
{
if ( is_debug_hexrays_ctree(level) )
{
for ( size_t i = 0, n = python_clearables.size(); i < n; ++i )
{
const hx_clearable_t &hxc = python_clearables[i];
debug_hexrays_ctree(level, "\t#%3d: %p (%d)\n", int(i), hxc.ptr, int(hxc.type));
}
}
}
//-------------------------------------------------------------------------
void hexrays_unloading__clear_python_clearable_references(void)
{
debug_hexrays_ctree("hexrays_unloading__clear_python_clearable_references()\n");
debug_hexrays_ctree(DCLVL_SIMPLE, "hexrays_unloading__clear_python_clearable_references()\n");
for ( size_t i = 0, n = python_clearables.size(); i < n; ++i )
{
const hx_clearable_t &hxc = python_clearables[i];
debug_hexrays_ctree("cleaning up %p (%d)\n", hxc.ptr, int(hxc.type));
debug_hexrays_ctree(DCLVL_SIMPLE, "cleaning up %p (%d)\n", hxc.ptr, int(hxc.type));
switch ( hxc.type )
{
case hxclr_cfuncptr:
@@ -244,7 +271,8 @@ void hexrays_register_python_clearable_instance(
hx_clearable_t &hxc = python_clearables.push_back();
hxc.ptr = ptr;
hxc.type = type;
debug_hexrays_ctree("registered %p\n", hxc.ptr);
debug_hexrays_ctree(DCLVL_SIMPLE, "registered %p\n", hxc.ptr);
debug_hexrays_dump_clearable_instances(DCLVL_FULL);
}
//-------------------------------------------------------------------------
@@ -253,16 +281,18 @@ void hexrays_register_python_clearable_instance(
// runtime, or it will be done by the C tree itself later.
void hexrays_deregister_python_clearable_instance(void *ptr)
{
debug_hexrays_ctree(DCLVL_SIMPLE, "maybe de-registering %p\n", ptr);
for ( size_t i = 0, n = python_clearables.size(); i < n; ++i )
{
const hx_clearable_t &hxc = python_clearables[i];
if ( hxc.ptr == ptr )
{
debug_hexrays_ctree(DCLVL_SIMPLE, "de-registered %p\n", hxc.ptr);
python_clearables.erase(python_clearables.begin() + i);
debug_hexrays_ctree("de-registered %p\n", hxc.ptr);
break;
}
}
debug_hexrays_dump_clearable_instances(DCLVL_FULL);
}
//-------------------------------------------------------------------------
@@ -278,46 +308,23 @@ hx_clearable_type_t hexrays_is_registered_python_clearable_instance(
//-------------------------------------------------------------------------
//
//-------------------------------------------------------------------------
static bool is_hexrays_plugin(const plugin_info_t *pinfo)
static bool is_hexrays_plugin(const plugin_t *entry)
{
bool is_hx = false;
if ( pinfo != NULL && pinfo->entry != NULL )
{
const plugin_t *p = pinfo->entry;
if ( streq(p->wanted_name, MODULE_NAME) )
is_hx = true;
}
return is_hx;
return entry != nullptr && streq(entry->wanted_name, MODULE_NAME);
}
//-------------------------------------------------------------------------
static void try_init()
{
init_hexrays_plugin(0);
if ( hexdsp != NULL )
if ( get_hexdsp() != nullptr )
msg("IDAPython Hex-Rays bindings initialized.\n");
}
//-------------------------------------------------------------------------
static void *idaapi exit_time_dummy_hexdsp(int /*code*/, ...)
{
/* This callback exists to avoid crashes if the user calls any hexrays functions
after unloading the decompiler.
switch ( code )
{
case hx_cexpr_t_cleanup: break;
case hx_cinsn_t_cleanup: break;
default: break;
}*/
return NULL;
}
//-------------------------------------------------------------------------
inline bool hexdsp_inited()
{
return hexdsp != NULL
&& hexdsp != init_time_dummy_hexdsp
&& hexdsp != exit_time_dummy_hexdsp;
return get_hexdsp() != nullptr;
}
//-------------------------------------------------------------------------
@@ -330,18 +337,19 @@ static ssize_t idaapi ida_hexrays_ui_notification(void *, int code, va_list va)
if ( !hexdsp_inited() )
{
const plugin_info_t *pi = va_arg(va, plugin_info_t *);
if ( is_hexrays_plugin(pi) )
if ( pi != nullptr && is_hexrays_plugin(pi->entry) )
try_init();
}
break;
case ui_plugin_unloading:
if ( hexdsp != NULL && hexdsp != init_time_dummy_hexdsp )
case ui_destroying_plugmod:
if ( get_hexdsp() != nullptr )
{
const plugin_info_t *pi = va_arg(va, plugin_info_t *);
if ( is_hexrays_plugin(pi) )
/*const plugmod_t *plugmod =*/ va_arg(va, plugmod_t *);
const plugin_t *entry = va_arg(va, plugin_t *);
if ( is_hexrays_plugin(entry) )
{
QASSERT(30500, hexdsp != exit_time_dummy_hexdsp);
QASSERT(30500, !do_not_check_ctree);
// Make sure all the refcounted objects are cleared right away.
hexrays_unloading__clear_python_clearable_references();
@@ -349,12 +357,12 @@ static ssize_t idaapi ida_hexrays_ui_notification(void *, int code, va_list va)
// Make sure all hooks are unhooked
hexrays_unloading__unhook_hooks();
hexdsp = exit_time_dummy_hexdsp;
do_not_check_ctree = true;
}
}
break;
case ui_database_closed:
hexdsp = init_time_dummy_hexdsp;
do_not_check_ctree = false;
break;
}
return 0;
@@ -389,9 +397,9 @@ static bool remove_udc_filter(udc_filter_t *instance)
//<inline(py_hexrays)>
//-------------------------------------------------------------------------
void py_debug_hexrays_ctree(const char *msg)
void py_debug_hexrays_ctree(int level, const char *msg)
{
debug_hexrays_ctree(msg);
debug_hexrays_ctree(level, msg);
}
//---------------------------------------------------------------------
+12 -2
View File
@@ -90,13 +90,23 @@ private:
newref_t py_rc(PySequence_GetItem(o, 0));
newref_t py_hint(PySequence_GetItem(o, 1));
newref_t py_implines(PySequence_GetItem(o, 2));
qstring plugin_hint;
if ( IDAPyInt_Check(py_rc.o)
&& IDAPyStr_Check(py_hint.o)
&& IDAPyInt_Check(py_implines.o)
&& IDAPyStr_AsUTF8(out_hint, py_hint.o) )
&& IDAPyStr_AsUTF8(&plugin_hint, py_hint.o) )
{
if ( !out_hint->empty()
&& out_hint->last() != '\n'
&& !plugin_hint.empty() )
{
out_hint->append('\n');
}
out_hint->append(plugin_hint);
rc = IDAPyInt_AsLong(py_rc.o);
*out_implines = IDAPyInt_AsLong(py_implines.o);
if ( rc == 2 )
rc = 0;
*out_implines += IDAPyInt_AsLong(py_implines.o);
}
}
return rc;
+1 -1
View File
@@ -45,7 +45,7 @@ idainfo_get_pack_mode = inf_get_pack_mode
idainfo_set_pack_mode = inf_set_pack_mode
__make_idainfo_accessors(None, "get_pack_mode", "set_pack_mode")
idainfo_is_32bit = inf_is_32bit
def idainfo_is_32bit(): return not inf_is_16bit() # in reality this means "is 32bit or higher"
__make_idainfo_getter("is_32bit")
idainfo_is_64bit = inf_is_64bit
+1 -1
View File
@@ -312,7 +312,7 @@ class PyIdc_cvt_refclass__(pyidc_cvt_helper__):
def as_cstr(val):
"""
Returns a C str from the passed value. The passed value can be of type refclass (returned by a call to buffer() or byref())
It scans for the first \x00 and returns the string value up to that point.
It scans for the first \\x00 and returns the string value up to that point.
"""
if isinstance(val, PyIdc_cvt_refclass__):
val = val.value
+5
View File
@@ -0,0 +1,5 @@
//<inline(py_ieee)>
typedef bytevec_t bytevec12_t;
typedef bytevec_t bytevec10_t;
//</inline(py_ieee)>
+11
View File
@@ -0,0 +1,11 @@
# Note that we DON'T define EZERO/EONE/ETWO to be fpvalue_t objects,
# because there is no way to make them read-only, which means EZERO
# could represent something entirely different from zero if the
# user mistakenly modifies it.
#<pycode(py_ieee)>
EZERO = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
EONE = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\xFF\x3F"
ETWO = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x40"
#</pycode(py_ieee)>
+37 -12
View File
@@ -10,13 +10,13 @@
// Context structure used by add|del_idc_hotkey()
struct py_idchotkey_ctx_t
{
qstring hotkey;
qstring action_name;
ref_t pyfunc;
py_idchotkey_ctx_t(
const char *_hotkey,
const char *_action_name,
PyObject *_pyfunc)
: hotkey(_hotkey),
: action_name(_action_name),
pyfunc(borref_t(_pyfunc)) {}
};
@@ -411,7 +411,7 @@ bool py_del_hotkey(PyObject *pyctx)
return false;
py_idchotkey_ctx_t *ctx = (py_idchotkey_ctx_t *) PyCapsule_GetPointer(pyctx, VALID_CAPSULE_NAME);
if ( ctx == NULL || !del_idc_hotkey(ctx->hotkey.c_str()) )
if ( ctx == NULL || !unregister_action(ctx->action_name.c_str()) )
return false;
delete ctx;
@@ -476,7 +476,7 @@ PyObject *py_add_hotkey(const char *hotkey, PyObject *pyfunc)
break;
// Create new context
py_idchotkey_ctx_t *ctx = new py_idchotkey_ctx_t(hotkey, pyfunc);
py_idchotkey_ctx_t *ctx = new py_idchotkey_ctx_t(idc_func_name.c_str(), pyfunc);
// Bind IDC variable w/ the PyCallable
gvar->set_pvoid(pyfunc);
@@ -486,7 +486,7 @@ PyObject *py_add_hotkey(const char *hotkey, PyObject *pyfunc)
} while (false);
}
// Cleanup
del_idc_hotkey(hotkey);
unregister_action(idc_func_name.c_str());
Py_RETURN_NONE;
}
@@ -893,14 +893,14 @@ private:
static ssize_t handle_hint_output(PyObject *o, qstring *hint, int *important_lines)
{
ssize_t rc = 0;
if ( o != NULL && PyTuple_Check(o) && PyTuple_Size(o) == 2 )
{
borref_t el0(PyTuple_GetItem(o, 0));
qstring plug_hint;
if ( el0 != NULL
&& IDAPyStr_Check(el0.o)
&& IDAPyStr_AsUTF8(hint, el0.o)
&& !hint->empty() )
&& IDAPyStr_AsUTF8(&plug_hint, el0.o)
&& !plug_hint.empty() )
{
borref_t el1(PyTuple_GetItem(o, 1));
if ( el1 != NULL && IDAPyInt_Check(el1.o) )
@@ -908,13 +908,15 @@ private:
long lns = IDAPyInt_AsLong(el1.o);
if ( lns > 0 )
{
*important_lines = lns;
rc = 1;
if ( !hint->empty() && hint->last() != '\n' )
hint->append('\n');
hint->append(plug_hint);
*important_lines += lns;
}
}
}
}
return rc;
return 0;
}
static ssize_t handle_hint_output(PyObject *o, qstring *hint, ea_t, int, int *important_lines)
@@ -1041,6 +1043,29 @@ struct disasm_line_t
DECLARE_TYPE_AS_MOVABLE(disasm_line_t);
typedef qvector<disasm_line_t> disasm_text_t;
//-------------------------------------------------------------------------
// tuple(fields, icon, attr)
static PyObject *py_chooser_base_t_get_row(
const chooser_base_t *chobj,
size_t n)
{
qstrvec_t fields;
fields.resize(chobj->columns);
chooser_item_attrs_t *attrs = new chooser_item_attrs_t;
int icon;
chobj->get_row(&fields, &icon, attrs, n);
PyObject *tuple = PyTuple_New(3);
PyTuple_SetItem(tuple, 0, qstrvec2pylist(fields));
PyTuple_SetItem(tuple, 1, IDAPyInt_FromLong(icon));
PyObject *py_attrs = SWIG_NewPointerObj(
SWIG_as_voidptr(attrs),
SWIGTYPE_p_chooser_item_attrs_t,
SWIG_POINTER_OWN);
PyTuple_SetItem(tuple, 2, py_attrs);
return tuple;
}
//-------------------------------------------------------------------------
void py_gen_disasm_text(disasm_text_t &text, ea_t ea1, ea_t ea2, bool truncate_lines)
{
-12
View File
@@ -1,17 +1,5 @@
# -----------------------------------------------------------------------
#<pycode(py_kernwin)>
DP_LEFT = 0x0001
DP_TOP = 0x0002
DP_RIGHT = 0x0004
DP_BOTTOM = 0x0008
DP_INSIDE = 0x0010
# if not before, then it is after
# (use DP_INSIDE | DP_BEFORE to insert a tab before a given tab)
# this flag alone cannot be used to determine orientation
DP_BEFORE = 0x0020
# used with combination of other flags
DP_TAB = 0x0040
DP_FLOATING = 0x0080
# ----------------------------------------------------------------------
def load_custom_icon(file_name=None, data=None, format=None):
+84 -49
View File
@@ -14,59 +14,64 @@ static void py_get_int(PyObject *self, T *prm, const char *name)
enum feature_t
{
CFEAT_INIT = 0x0001,
CFEAT_GETICON = 0x0002,
CFEAT_GETATTR = 0x0004,
CFEAT_INS = 0x0008,
CFEAT_DEL = 0x0010,
CFEAT_EDIT = 0x0020,
CFEAT_ENTER = 0x0040,
CFEAT_REFRESH = 0x0080,
CFEAT_SELECT = 0x0100,
CFEAT_ONCLOSE = 0x0200,
CFEAT_EMBEDDED = 0x0400,
CFEAT_GETDIRTREE = 0x0800,
CFEAT_INDEX2INODE = 0x1000,
CFEAT_INIT = 0x0001,
CFEAT_GETICON = 0x0002,
CFEAT_GETATTR = 0x0004,
CFEAT_INS = 0x0008,
CFEAT_DEL = 0x0010,
CFEAT_EDIT = 0x0020,
CFEAT_ENTER = 0x0040,
CFEAT_REFRESH = 0x0080,
CFEAT_SELECT = 0x0100,
CFEAT_ONCLOSE = 0x0200,
CFEAT_EMBEDDED = 0x0400,
CFEAT_GETDIRTREE = 0x0800,
CFEAT_INDEX2INODE = 0x1000,
CFEAT_INDEX2DIFFPOS = 0x2000,
};
//------------------------------------------------------------------------
// we do not use virtual subclasses so we use #define for common code
#define DEFINE_COMMON_CALLBACKS \
virtual const void *get_obj_id(size_t *len) const override \
{ \
return mixin_get_obj_id(len); \
} \
virtual void *get_chooser_obj() override \
{ \
return mixin_get_chooser_obj(); \
} \
virtual bool idaapi init() override \
{ \
return mixin_init(this); \
} \
virtual size_t idaapi get_count() const override \
{ \
return mixin_get_count(); \
} \
virtual void idaapi get_row( \
qstrvec_t *cols, \
int *icon_, \
chooser_item_attrs_t *attrs, \
size_t n) const override \
{ \
mixin_get_row(cols, icon_, attrs, n, this); \
} \
virtual void idaapi closed() override \
{ \
mixin_closed(this); \
} \
virtual dirtree_t *idaapi get_dirtree() override \
{ \
return mixin_get_dirtree(this); \
} \
virtual inode_t idaapi index_to_inode(size_t n) const override \
{ \
return mixin_index_to_inode(n); \
#define DEFINE_COMMON_CALLBACKS \
virtual const void *get_obj_id(size_t *len) const override \
{ \
return mixin_get_obj_id(len); \
} \
virtual void *get_chooser_obj() override \
{ \
return mixin_get_chooser_obj(); \
} \
virtual bool idaapi init() override \
{ \
return mixin_init(this); \
} \
virtual size_t idaapi get_count() const override \
{ \
return mixin_get_count(); \
} \
virtual void idaapi get_row( \
qstrvec_t *cols, \
int *icon_, \
chooser_item_attrs_t *attrs, \
size_t n) const override \
{ \
mixin_get_row(cols, icon_, attrs, n, this); \
} \
virtual void idaapi closed() override \
{ \
mixin_closed(this); \
} \
virtual dirtree_t *idaapi get_dirtree() override \
{ \
return mixin_get_dirtree(this); \
} \
virtual inode_t idaapi index_to_inode(size_t n) const override \
{ \
return mixin_index_to_inode(n); \
} \
virtual diffpos_t idaapi index_to_diffpos(size_t n) const override \
{ \
return mixin_index_to_diffpos(n); \
}
@@ -226,6 +231,7 @@ bool py_chooser_props_t::do_extract_from_pyobject(
{ S_ON_CLOSE, CFEAT_ONCLOSE, 0 },
{ S_ON_GET_DIRTREE, CFEAT_GETDIRTREE, CH_HAS_DIRTREE },
{ S_ON_INDEX_TO_INODE, CFEAT_INDEX2INODE, CH_HAS_DIRTREE },
{ S_ON_INDEX_TO_DIFFPOS, CFEAT_INDEX2DIFFPOS, CH_HAS_DIFF },
};
// we can forbid some callbacks explicitly
uint32 forbidden_cb = 0;
@@ -305,6 +311,7 @@ protected:
void mixin_closed(chooser_base_t *chobj);
dirtree_t *mixin_get_dirtree(const chooser_base_t *chobj);
inode_t mixin_index_to_inode(size_t n) const;
diffpos_t mixin_index_to_diffpos(size_t n) const;
void mixin_init_chooser_base_from_props(chooser_base_t *cb);
private:
@@ -497,6 +504,24 @@ inode_t py_chooser_mixin_t::mixin_index_to_inode(size_t n) const
return inode;
}
//-------------------------------------------------------------------------
diffpos_t py_chooser_mixin_t::mixin_index_to_diffpos(size_t n) const
{
diffpos_t diffpos = diffpos_t(-1); // BADDIFF;
if ( has_feature(CFEAT_INDEX2DIFFPOS) )
{
PYW_GIL_GET;
pycall_res_t pyres(PyObject_CallMethod(self.o, (char *) S_ON_INDEX_TO_DIFFPOS, PY_BV_SZ, Py_ssize_t(n)));
if ( pyres.result != NULL )
{
uint64 u64;
if ( PyW_GetNumber(pyres.result.o, &u64) )
diffpos = diffpos_t(u64);
}
}
return diffpos;
}
//-------------------------------------------------------------------------
void py_chooser_mixin_t::mixin_init_chooser_base_from_props(
chooser_base_t *cb)
@@ -820,6 +845,16 @@ PyObject *choose_find(const char *title)
//---------------------------------------------------------------------------
//<inline(py_kernwin_choose)>
#define CHOOSER_NO_SELECTION 0x01
#define CHOOSER_MULTI_SELECTION 0x02
#define CHOOSER_POPUP_MENU 0x04
// The following are obsolete, only present for bw-compat
#define CHOOSER_MENU_EDIT 0
#define CHOOSER_MENU_JUMP 1
#define CHOOSER_MENU_SEARCH 2
PyObject *choose_find(const char *title);
void choose_refresh(PyObject *self);
void choose_close(PyObject *self);
+7
View File
@@ -62,6 +62,10 @@ class Choose(object):
CH_RESTORE = _ida_kernwin.CH_RESTORE
"""restore floating position if present (equivalent of WOPN_RESTORE) (GUI version only)"""
CH_RENAME_IS_EDIT = _ida_kernwin.CH_RENAME_IS_EDIT
"""triggering a 'edit/rename' (i.e., F2 shortcut) on a cell,
should call the edit() callback for the corresponding row."""
CH_BUILTIN_SHIFT = _ida_kernwin.CH_BUILTIN_SHIFT
CH_BUILTIN_MASK = _ida_kernwin.CH_BUILTIN_MASK
@@ -69,6 +73,9 @@ class Choose(object):
can be provided to the user (instead of a flat table)"""
CH_HAS_DIRTREE = _ida_kernwin.CH_HAS_DIRTREE
"""The chooser can be used in a diffing/merging workflow"""
CH_HAS_DIFF = _ida_kernwin.CH_HAS_DIFF
# column flags (are specified in the widths array)
CHCOL_PLAIN = _ida_kernwin.CHCOL_PLAIN
CHCOL_PATH = _ida_kernwin.CHCOL_PATH
+28 -20
View File
@@ -13,44 +13,49 @@ class PluginForm(object):
WOPN_MDI = 0x01 # no-op
WOPN_TAB = 0x02 # no-op
WOPN_RESTORE = 0x04
WOPN_RESTORE = _ida_kernwin.WOPN_RESTORE
"""
if the widget is the only widget in a floating area when
it is closed, remember that area's geometry. The next
time that widget is created as floating (i.e., WOPN_DP_FLOATING)
its geometry will be restored (e.g., "Execute script"
"""
WOPN_ONTOP = 0x08 # no-op
WOPN_MENU = 0x10 # no-op
WOPN_CENTERED = 0x20 # no-op
WOPN_PERSIST = 0x40
WOPN_ONTOP = 0x08 # no-op
WOPN_MENU = 0x10 # no-op
WOPN_CENTERED = 0x20 # no-op
WOPN_PERSIST = _ida_kernwin.WOPN_PERSIST
"""form will persist until explicitly closed with Close()"""
WOPN_DP_LEFT = 0x00010000
WOPN_DP_LEFT = _ida_kernwin.WOPN_DP_LEFT
""" Dock widget to the left of dest_ctrl"""
WOPN_DP_TOP = 0x00020000
WOPN_DP_TOP = _ida_kernwin.WOPN_DP_TOP
""" Dock widget above dest_ctrl"""
WOPN_DP_RIGHT = 0x00040000
WOPN_DP_RIGHT = _ida_kernwin.WOPN_DP_RIGHT
""" Dock widget to the right of dest_ctrl"""
WOPN_DP_BOTTOM = 0x00080000
WOPN_DP_BOTTOM = _ida_kernwin.WOPN_DP_BOTTOM
""" Dock widget below dest_ctrl"""
WOPN_DP_INSIDE = 0x00100000
WOPN_DP_INSIDE = _ida_kernwin.WOPN_DP_INSIDE
""" Create a new tab bar with both widget and dest_ctrl"""
WOPN_DP_TAB = 0x00400000
WOPN_DP_TAB = _ida_kernwin.WOPN_DP_TAB
"""
Place widget into a tab next to dest_ctrl,
if dest_ctrl is in a tab bar
(otherwise the same as #WOPN_DP_INSIDE)
"""
WOPN_DP_BEFORE = 0x00200000
WOPN_DP_BEFORE = _ida_kernwin.WOPN_DP_BEFORE
"""
place widget before dst_form in the tab bar instead of after
used with #WOPN_DP_INSIDE and #WOPN_DP_TAB
"""
WOPN_DP_FLOATING=0x00800000
WOPN_DP_FLOATING = _ida_kernwin.WOPN_DP_FLOATING
"""
When floating or in a splitter (i.e., not tabbed),
use the widget's size hint to determine the best
geometry (Qt only)
"""
WOPN_DP_SZHINT = _ida_kernwin.WOPN_DP_SZHINT
""" Make widget floating"""
WOPN_DP_INSIDE_BEFORE = WOPN_DP_INSIDE | WOPN_DP_BEFORE
WOPN_DP_TAB_BEFORE = WOPN_DP_TAB | WOPN_DP_BEFORE
WOPN_DP_INSIDE_BEFORE = _ida_kernwin.WOPN_DP_INSIDE_BEFORE
WOPN_DP_TAB_BEFORE = _ida_kernwin.WOPN_DP_TAB_BEFORE
WOPN_CREATE_ONLY = {}
@@ -180,17 +185,20 @@ class PluginForm(object):
return _ida_kernwin.plgform_get_widget(self.__clink__)
WCLS_SAVE = 0x1
WCLS_SAVE = _ida_kernwin.WCLS_SAVE
"""Save state in desktop config"""
WCLS_NO_CONTEXT = 0x2
WCLS_NO_CONTEXT = _ida_kernwin.WCLS_NO_CONTEXT
"""Don't change the current context (useful for toolbars)"""
WCLS_DONT_SAVE_SIZE = 0x4
WCLS_DONT_SAVE_SIZE = _ida_kernwin.WCLS_DONT_SAVE_SIZE
"""Don't save size of the window"""
WCLS_CLOSE_LATER = 0x8
WCLS_DELETE_LATER = _ida_kernwin.WCLS_DELETE_LATER
"""This flag should be used when Close() is called from an event handler"""
WCLS_CLOSE_LATER = WCLS_DELETE_LATER
#</pycode(py_kernwin_plgform)>
plg = PluginForm()
+2 -2
View File
@@ -6,9 +6,9 @@ def get_switch_info(*args):
else:
si, ea = args
return None if _real_get_switch_info(si, ea) <= 0 else si
def get_abi_name(*args):
def get_abi_name():
import ida_typeinf
return ida_typeinf.get_abi_name(args)
return ida_typeinf.get_abi_name()
#</pycode(py_nalt)>
#<pycode_BC695(py_nalt)>
+31
View File
@@ -3,6 +3,37 @@
#define __PY_STRUCT__
//<inline(py_struct)>
//-------------------------------------------------------------------------
/*
#<pydoc>
def get_innermost_member(sptr, offset):
"""
Get the innermost member at the given offset
@param sptr: the starting structure
@param offset: offset into the starting structure
@return:
- None on failure
- tuple(member_t, struct_t, offset)
where member_t: a member in SPTR (it is not a structure),
struct_t: the innermost structure,
offset: remaining offset into the returned member
"""
pass
#</pydoc>
*/
PyObject *py_get_innermost_member(struc_t *sptr, asize_t offset)
{
PYW_GIL_CHECK_LOCKED_SCOPE();
member_t *mptr = get_innermost_member(&sptr, &offset);
if ( mptr == nullptr )
Py_RETURN_NONE;
return Py_BuildValue("(OO" PY_BV_ASIZE ")",
SWIG_NewPointerObj(SWIG_as_voidptr(mptr), SWIGTYPE_p_member_t, 0),
SWIG_NewPointerObj(SWIG_as_voidptr(sptr), SWIGTYPE_p_struc_t, 0),
bvasize_t(offset));
}
//</inline(py_struct)>
#endif // __PY_STRUCT__
+2 -1
View File
@@ -4,7 +4,7 @@
#
# Misc constants
#
UA_MAXOP = 6
UA_MAXOP = 8
# ----------------------------------------------------------------------
# instruc_t related constants
@@ -256,6 +256,7 @@ OOF_ZSTROFF = 0x0200 # meaningful only if is_stroff(uFlag)
OOF_NOBNOT = 0x0400 # prohibit use of binary not
OOF_SPACES = 0x0800 # do not suppress leading spaces
# currently works only for floating point numbers
OOF_ANYSERIAL = 0x1000 # if enum: select first available serial
# ----------------------------------------------------------------------
+600 -80
View File
File diff suppressed because it is too large Load Diff
+600 -80
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+9 -4
View File
@@ -36,9 +36,10 @@
%ignore get_bytes;
%ignore get_strlit_contents;
%ignore get_hex_string;
%ignore bin_search2;
%ignore bin_search; // we redefine our own, w/ 2 params swapped, so we can apply the typemaps below
%rename (bin_search) py_bin_search;
%rename (bin_search) bin_search2;
%ignore bin_search2(ea_t, ea_t, const uchar *, const uchar *, size_t, int);
%ignore get_8bit;
%rename (get_8bit) py_get_8bit;
@@ -46,9 +47,7 @@
%ignore get_octet;
%rename (get_octet) py_get_octet;
%ignore compiled_binpat_t;
%ignore compiled_binpat_vec_t;
%ignore parse_binpat_str;
%template(compiled_binpat_vec_t) qvector<compiled_binpat_t>;
// TODO: This could be fixed (if needed)
%ignore set_dbgmem_source;
@@ -177,8 +176,14 @@
%include "bytes.hpp"
// Make it so that 'imask' can be None
%apply (const bytevec_t &_fields) { const bytevec_t &imask };
%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) const bytevec_t &imask
{ // %typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) const bytevec_t &imask
$1 = ($input == Py_None || IDAPyBytes_Check($input)) ? 1 : 0;
}
//
%clear(void *buf, ssize_t size);
%clear(const void *buf, size_t size);
-5
View File
@@ -91,13 +91,8 @@
%extend idc_value_t
{
wrapped_array_t<ushort,6> __get_e() {
return wrapped_array_t<ushort,6>($self->e);
}
%pythoncode {
str = property(lambda self: self.c_str(), lambda self, v: self.set_string(v))
e = property(__get_e)
}
}
+1
View File
@@ -21,6 +21,7 @@
%ignore func_t::llabelqty;
%ignore func_t::llabels;
%ignore FUNC_RESERVED;
%template (dyn_stkpnt_array) dynamic_wrapped_array_t<stkpnt_t>;
%template (dyn_regvar_array) dynamic_wrapped_array_t<regvar_t>;
+6 -2
View File
@@ -2,8 +2,12 @@
#include <gdl.hpp>
%}
%ignore cancellable_graph_t;
%ignore gdl_graph_t;
%ignore gdl_graph_t::gen_gdl;
%ignore gdl_graph_t::gen_dot;
%ignore gdl_graph_t::path_exists;
%ignore cancellable_graph_t::padding;
%ignore cancellable_graph_t::check_cancel;
%ignore intmap_t;
%ignore intset_t;
+27 -18
View File
@@ -18,36 +18,41 @@
// most of these aren't defined/exported through graph.hpp
%ignore abstract_graph_t::callback;
%ignore abstract_graph_t;
%ignore abstract_graph_t::vgrcall;
%ignore abstract_graph_t::clear;
%ignore abstract_graph_t::dump_graph;
%ignore abstract_graph_t::calc_bounds;
%ignore abstract_graph_t::calc_fitting_params;
%ignore abstract_graph_t::for_all_nodes_edges;
%ignore abstract_graph_t::get_edge_ports;
%ignore abstract_graph_t::add_node_edges;
%ignore abstract_graph_t::create_polar_tree_layout;
%ignore abstract_graph_t::create_radial_tree_layout;
%ignore abstract_graph_t::create_orthogonal_layout;
%ignore abstract_graph_t::clone;
%ignore abstract_graph_t::nrect;
%rename (nrect) my_nrect;
%ignore abstract_graph_t::get_edge;
%rename (get_edge) my_get_edge;
%ignore edge_info_t::add_layout_point;
%ignore edge_infos_wrapper_t::edge_infos_wrapper_t;
%ignore edge_infos_wrapper_t::~edge_infos_wrapper_t;
%ignore graph_dispatcher;
%ignore graph_item_t::operator==;
%ignore mutable_graph_t::add_edge;
%ignore mutable_graph_t::add_node;
// Meant to be constructed by the kernel/ui only
%feature("nodirector") mutable_graph_t;
%ignore mutable_graph_t::mutable_graph_t;
%ignore mutable_graph_t::calc_center_of;
%ignore mutable_graph_t::change_visibility;
%ignore mutable_graph_t::check_new_group;
%ignore mutable_graph_t::clone;
%ignore mutable_graph_t::del_edge;
%ignore mutable_graph_t::del_node;
%ignore mutable_graph_t::fix_collapsed_group_edges;
%ignore mutable_graph_t::get_edge(edge_t);
%rename (get_edge) my_get_edge;
%ignore mutable_graph_t::groups_are_present;
%ignore mutable_graph_t::insert_simple_nodes;
%ignore mutable_graph_t::insert_visible_nodes;
%ignore mutable_graph_t::move_grouped_nodes;
%ignore mutable_graph_t::move_to_same_place;
%ignore mutable_graph_t::mutable_graph_t;
%ignore mutable_graph_t::redo_layout;
%ignore mutable_graph_t::refresh;
%ignore mutable_graph_t::replace_edge;
%ignore mutable_graph_t::resize;
%ignore mutable_graph_t::set_nrect;
%ignore node_ordering_t::clr;
%ignore node_ordering_t::order;
%ignore point_t::dstr;
%ignore point_t::print;
%ignore pointseq_t::dstr;
@@ -62,12 +67,16 @@ public:
virtual int idaapi visit_edge(edge_t /*e*/, edge_info_t * /*ei*/) { qnotused(self); return 0; }
}
%extend mutable_graph_t {
%extend abstract_graph_t {
public:
virtual edge_info_t my_get_edge(edge_t e)
{
return *($self->get_edge(e));
}
virtual rect_t my_nrect(int n)
{
return $self->nrect(n);
}
}
%template(screen_graph_selection_base_t) qvector<selection_item_t>;
+37 -14
View File
@@ -1,4 +1,7 @@
%{
#undef HEXDSP
hexdsp_t *get_idapython_hexdsp();
#define HEXDSP get_idapython_hexdsp()
#include <hexrays.hpp>
%}
@@ -39,6 +42,10 @@ SWIGINTERN void __raise_vdf(const vd_failure_t &e)
%include <windows.i>
#endif
%typemap(check) const tinfo_t *type {
// %typemap(check) const tinfo_t *type
}
%define %define_hexrays_lifecycle_object(TypeName)
%feature("ref") TypeName
{
@@ -147,8 +154,11 @@ SWIGINTERN void __raise_vdf(const vd_failure_t &e)
%feature("nodirector") codegen_t;
%ignore codegen_t::reserved;
%feature("nodirector") simple_graph_t;
%ignore simple_graph_t::simple_graph_t;
%ignore simple_graph_t::~simple_graph_t;
%feature("nodirector") mbl_graph_t;
%ignore mbl_graph_t::mbl_graph_t;
%ignore mbl_graph_t::~mbl_graph_t;
@@ -208,6 +218,15 @@ SWIGINTERN void __raise_vdf(const vd_failure_t &e)
}
};
%extend mba_t {
%pythoncode {
"""
Deprecated. Please do not use.
"""
idb_node = property(lambda self: self.deprecated_idb_node)
}
};
%ignore op_parent_info_t::really_alloc;
%ignore getf_reginsn(const minsn_t *);
@@ -289,6 +308,8 @@ SWIGINTERN void __raise_vdf(const vd_failure_t &e)
%rename (_ll_make_num) make_num;
%rename (_ll_create_helper) create_helper;
%delobject create_cfunc;
%extend cfunc_t {
%immutable argidx;
@@ -361,10 +382,13 @@ public:
raise Exception("%s already owns attribute \"%s\" (%s); cannot be modified" % (self, attr, o))
return True
def _ensure_ownership_transferrable(self, v):
if not v.thisown:
raise Exception("%s is already owned, and cannot be reused" % v)
def _acquire_ownership(self, v, acquire):
if acquire and (v is not None) and not isinstance(v, ida_idaapi.integer_types):
if not v.thisown:
raise Exception("%s is already owned, and cannot be reused" % v)
self._ensure_ownership_transferrable(v)
v.thisown = False
dereg = getattr(v, "_deregister", None)
if dereg:
@@ -662,6 +686,17 @@ cexpr_t *citem_t_cexpr_get(citem_t *item) { return (cexpr_t *) item; }
CEXPR_MEMBER_REF_STR(char*, string, self.op == cot_str, None);
};
%feature("pythonprepend") cexpr_t::cexpr_t %{
for arg in args[1:]: # skip copy constructor's arg
if isinstance(arg, cexpr_t):
self._ensure_ownership_transferrable(arg)
%}
%feature("pythonappend") cexpr_t::cexpr_t %{
for arg in args[1:]: # skip copy constructor's arg
if isinstance(arg, cexpr_t):
self._acquire_ownership(arg, True)
%}
#undef CEXPR_MEMBER_REF_STR
#undef CEXPR_MEMBER_REF
@@ -956,18 +991,6 @@ void qswap(cinsn_t &a, cinsn_t &b);
%possible_director_exc(ctree_visitor_t::apply_to)
%possible_director_exc(ctree_visitor_t::apply_to_exprs)
%template (fnum_array) wrapped_array_t<uint16,6>;
%extend fnumber_t {
wrapped_array_t<uint16,6> __get_fnum() {
return wrapped_array_t<uint16,6>($self->fnum);
}
%pythoncode {
fnum = property(__get_fnum)
}
}
%inline %{
//<inline(py_hexrays)>
//</inline(py_hexrays)>
+1 -1
View File
@@ -31,7 +31,7 @@
%uncomparable_elements_qvector(exception_info_t, excvec_t);
%uncomparable_elements_qvector(process_info_t, procinfo_vec_t);
%template(call_stack_t) qvector<call_stack_info_t>;
%template(call_stack_info_vec_t) qvector<call_stack_info_t>;
%template(meminfo_vec_t) qvector<memory_info_t>;
%include "idd.hpp"
+2
View File
@@ -57,6 +57,8 @@ struct undo_records_t;
%ignore ignore_micro_t;
%ignore procmod_t;
%ignore plugmod_t;
%ignore get_hexdsp;
%ignore set_hexdsp;
// @arnaud
%ignore notify__calc_next_eas;
+209
View File
@@ -0,0 +1,209 @@
%{
#include <ieee.h>
%}
%ignore ieee_ezero;
%ignore ieee_eone;
%ignore ieee_etwo;
%ignore ieee_e32;
%ignore ieee_elog2;
%ignore ieee_esqrt2;
%ignore ieee_eoneopi;
%ignore ieee_epi;
%ignore ieee_eeul;
%ignore realtoasc;
%ignore asctoreal;
%ignore eltoe;
%ignore eltoe64;
%ignore eltoe64u;
%ignore eetol;
%ignore eetol64;
%ignore eetol64u;
%ignore eldexp;
%ignore eadd;
%ignore emul;
%ignore ediv;
%ignore ecmp;
%ignore get_fpvalue_kind;
%ignore emovo;
%ignore emovi;
%ignore eshift;
%ignore emdnorm;
%ignore ieee_realcvt;
%ignore realcvt;
%ignore l_realcvt;
%ignore b_realcvt;
%typemap(argout) (char *buf, size_t bufsize)
{
// %typemap(argout) (char *buf, size_t bufsize) (ieee.i specialization)
Py_XDECREF(resultobj);
$result = IDAPyStr_FromUTF8($1);
}
%_uint_result_as_output(sval_t, PyLong_FromLong, result == REAL_ERROR_OK);
%_uint_result_as_output(int64, PyLong_FromLongLong, result == REAL_ERROR_OK);
%_uint_result_as_output(uint64, PyLong_FromUnsignedLongLong, result == REAL_ERROR_OK);
%apply sval_t *result { sval_t *out };
%apply int64 *result { int64 *out };
%apply uint64 *result { uint64 *out };
%inline %{
//<inline(py_ieee)>
//</inline(py_ieee)>
%}
%define %define_sized_bytevec_t(TYPE, SIZE)
%typemap(check) (const TYPE &)
{ // %typemap(check) (const TYPE)
if ( $1->size() != SIZE )
SWIG_exception_fail(
SWIG_ValueError,
"invalid bytes " "in method '" "$symname" "', argument " "$argnum"" should be " #SIZE " bytes long");
}
%enddef
%define_sized_bytevec_t(bytevec12_t, 12);
%define_sized_bytevec_t(bytevec10_t, 10);
%ignore fpvalue_t::from_half;
%ignore fpvalue_t::from_float;
%ignore fpvalue_t::from_double;
%ignore fpvalue_t::to_half;
%ignore fpvalue_t::to_float;
%ignore fpvalue_t::to_double;
%ignore fpvalue_t::from_str(const char **);
%template (fpvalue_shorts_array_t) wrapped_array_t<uint16,FPVAL_NWORDS>;
%extend fpvalue_t {
fpvalue_t()
{
fpvalue_t *fp = new fpvalue_t();
fp->clear();
return fp;
}
fpvalue_t(const bytevec12_t &in)
{
fpvalue_t *fp = new fpvalue_t();
memmove(fp->w, in.begin(), sizeof(fp->w));
return fp;
}
void _get_bytes(bytevec12_t *vout) const
{
vout->resize(12);
memmove(vout->begin(), (const void *) $self->w, vout->size());
}
void _set_bytes(const bytevec12_t &in)
{
memmove($self->w, (const void *) in.begin(), sizeof($self->w));
}
void _get_10bytes(bytevec10_t *vout) const
{
vout->resize(10);
memmove(vout->begin(), (const void *) $self->w, vout->size());
}
void _set_10bytes(const bytevec10_t &in)
{
memmove($self->w, (const void *) in.begin(), sizeof($self->w));
}
// yes, it's called '_get_float', but we return a 'double' because
// that 'double' will be for SWiG to turn the type into a Python
// floating-point value with as much accuracy as possible.
double _get_float() const
{
double v;
fpvalue_error_t err = $self->to_double(&v);
if ( err != REAL_ERROR_OK )
PyErr_SetString(
PyExc_ValueError,
"Raw data couldn't be converted to a floating-point number");
return v;
}
void _set_float(double v)
{
fpvalue_error_t err = $self->from_double(v);
if ( err != REAL_ERROR_OK )
PyErr_SetString(
PyExc_ValueError,
"The floating-point number couldn't be converted");
}
qstring __str__() const
{
char buf[MAXSTR];
$self->to_str(buf, sizeof(buf), 50);
qstring qs(buf);
qs.trim2();
return qs;
}
wrapped_array_t<uint16,FPVAL_NWORDS> _get_shorts()
{
return wrapped_array_t<uint16,FPVAL_NWORDS>($self->w);
}
fpvalue_error_t from_str(const char *p)
{
return p != nullptr ? $self->from_str(&p) : REAL_ERROR_BADSTR;
}
void assign(const fpvalue_t &r)
{
memmove($self->w, r.w, sizeof($self->w));
}
%pythoncode
{
bytes = property(_get_bytes, _set_bytes)
_10bytes = property(_get_10bytes, _set_10bytes)
shorts = property(_get_shorts)
float = property(_get_float, _set_float)
sval = property(lambda self: self.to_sval(), lambda self, v: self.from_sval(v))
int64 = property(lambda self: self.to_int64(), lambda self, v: self.from_int64(v))
uint64 = property(lambda self: self.to_uint64(), lambda self, v: self.from_uint64(v))
def __iter__(self):
shorts = self.shorts
for one in shorts:
yield one
def __getitem__(self, i):
return self.shorts[i]
def __setitem__(self, i, v):
self.shorts[i] = v
}
}
%define %define_fpvalue_t_operator(OPERATOR, METHOD, ERRMSG)
%nopythonmaybecall fpvalue_t::OPERATOR;
%extend fpvalue_t {
fpvalue_t OPERATOR(const fpvalue_t &o) const
{
fpvalue_t r = *$self;
fpvalue_error_t err = r.METHOD(o);
if ( err != REAL_ERROR_OK )
throw std::runtime_error(ERRMSG);
return r;
}
}
%enddef
%define_fpvalue_t_operator(__add__, fadd, "Addition failed");
%define_fpvalue_t_operator(__sub__, fsub, "Subtraction failed");
%define_fpvalue_t_operator(__mul__, fmul, "Multiplication failed");
%define_fpvalue_t_operator(__truediv__, fdiv, "Division failed");
%include "ieee.h"
%pythoncode %{
#<pycode(py_ieee)>
#</pycode(py_ieee)>
%}
+31 -4
View File
@@ -21,7 +21,9 @@ struct dirspec_t;
$result = PyLong_FromUnsignedLongLong((unsigned long long) $1);
}
%ignore callui_t;
%ignore sync_source_t::sync_source_t();
%ignore l_compare;
// Ignore the va_list functions
%ignore vask_form;
@@ -88,8 +90,6 @@ struct dirspec_t;
%ignore destroy_custom_viewerdestroy_custom_viewer;
%ignore set_custom_viewer_handler;
%ignore set_custom_viewer_range;
%ignore is_idaview;
%ignore refresh_custom_viewer;
%ignore set_custom_viewer_handlers;
%ignore get_viewer_name;
// Ignore these string functions. There are trivial replacements in Python.
@@ -138,6 +138,33 @@ struct dirspec_t;
%ignore chooser_item_attrs_t::cb;
// chooser_base_t should be read-only
%ignore chooser_base_t::chooser_base_t;
%ignore chooser_base_t::~chooser_base_t;
%ignore chooser_base_t::call_destructor;
%ignore chooser_base_t::check_version;
%ignore chooser_base_t::closed;
%ignore chooser_base_t::get_chooser_obj;
%ignore chooser_base_t::get_obj_id;
%ignore chooser_base_t::init;
%ignore chooser_base_t::set_ask_item_attrs;
%ignore chooser_base_t::ALL_CHANGED;
%ignore chooser_base_t::NOTHING_CHANGED;
%ignore chooser_base_t::SELECTION_CHANGED;
%ignore chooser_base_t::ALREADY_EXISTS;
%ignore chooser_base_t::EMPTY_CHOOSER;
%ignore chooser_base_t::NO_ATTR;
%ignore chooser_base_t::NO_SELECTION;
%feature("nodirector") chooser_base_t;
%ignore chooser_base_t::get_row(qstrvec_t *, int *, chooser_item_attrs_t *, size_t) const;
%extend chooser_base_t {
PyObject *get_row(size_t n) const
{
return py_chooser_base_t_get_row($self, n);
}
}
// Make ask_addr(), ask_seg(), and ask_long() return a
// tuple: (result, value)
%rename (_ask_long) ask_long;
@@ -163,8 +190,8 @@ struct dirspec_t;
%apply bytevec_t *vout { bytevec_t *out };
%ignore register_place_class;
%ignore register_loc_converter;
%ignore lookup_loc_converter;
%ignore register_loc_converter2;
%ignore lookup_loc_converter2;
%ignore hexplace_t;
%ignore hexplace_gen_t;
+3
View File
@@ -21,12 +21,15 @@
%ignore func_info_and_frequency_t::swap;
%ignore func_info_pattern_and_frequency_t::swap;
%ignore input_file_t::swap;
%ignore func_info_pattern_and_frequency_t::swap;
%ignore mdkey2str;
%ignore str2mdkey;
%ignore serialize;
%ignore deserialize;
%ignore new_lumina_client;
%ignore close_server_connection;
%ignore close_server_connection2;
%ignore close_server_connections;
%ignore get_mdkey_preferred_format;
%ignore extract_type_from_metadata;
%rename (extract_type_from_metadata) py_extract_type_from_metadata;
-7
View File
@@ -17,9 +17,6 @@
%ignore set_wide_value;
%ignore del_wide_value;
%ignore get_strid;
%ignore _set_strid;
%ignore _del_strid;
%ignore xrefpos_t;
%ignore get_xrefpos;
%ignore set_xrefpos;
@@ -64,10 +61,6 @@
%ignore set_jumptable_info;
%ignore get_jumptable_info;
%ignore refinfo_t::_get_target;
%ignore refinfo_t::_get_value;
%ignore refinfo_t::_get_opval;
%ignore custom_refinfo_handler_t;
%ignore custom_refinfo_handlers_t;
%ignore register_custom_refinfo;
+2
View File
@@ -73,6 +73,8 @@
%ignore netnode_inited;
%ignore netnode_is_available;
%ignore netnode_copy;
%ignore netnode_copy2;
%ignore netnode_copyto2;
%ignore netnode_altshift;
%ignore netnode_charshift;
%ignore netnode_supshift;
+6
View File
@@ -47,6 +47,12 @@
}
}
// I am not sure how else to proceed for SWiG to not attempt
// generating a setter...
%ignore BADDIFF;
%rename (BADDIFF) _BADDIFF;
%constant diffpos_t _BADDIFF = diffpos_t(-1);
//<typemaps(pro)>
//</typemaps(pro)>
+4
View File
@@ -21,6 +21,10 @@
{
ea_t start_ea;
ea_t end_ea;
%pythoncode {
use64 = is_64bit
}
}
#ifdef __EA64__
+23
View File
@@ -0,0 +1,23 @@
%{
#include <srclang.hpp>
%}
%ignore srclang_parser_t;
%ignore srclang_parsers_t;
%ignore srclang_parser_obj_t;
%ignore install_srclang_parser;
%ignore remove_srclang_parser;
%ignore select_srclang_parser;
%ignore get_srclang_parser_internal;
%ignore get_current_srclang_parser;
%ignore srclang_parser_visitor_t;
%ignore for_all_srclang_parsers;
%ignore find_parser_kind_t;
%ignore find_srclang_parser;
%ignore find_parser_by_idx;
%ignore find_parser_by_name;
%ignore find_parser_by_srclang;
%ignore init_srclang_parser;
%ignore term_srclang_parser;
%include "srclang.hpp"
+3
View File
@@ -7,6 +7,9 @@
%ignore get_member_name(tid_t);
%ignore get_member_by_id(tid_t, struc_t **); // allow version w/ qstring* only
%ignore get_innermost_member;
%rename (get_innermost_member) py_get_innermost_member;
//-------------------------------------------------------------------------
// For 'get_member_by_id()'
%typemap(in,numinputs=0) qstring *out_mname (qstring temp) {
+2
View File
@@ -5,6 +5,8 @@
// Most of these could be wrapped if needed
%ignore get_cc;
%ignore get_effective_cc;
%ignore ::use_golang_abi;
%ignore get_cc_type_size;
%ignore get_de;
%ignore skip_ptr_type_header;
+2
View File
@@ -88,6 +88,8 @@
Op4 = property(lambda self: self.__get_operand__(3))
Op5 = property(lambda self: self.__get_operand__(4))
Op6 = property(lambda self: self.__get_operand__(5))
Op7 = property(lambda self: self.__get_operand__(6))
Op8 = property(lambda self: self.__get_operand__(7))
auxpref = property(__get_auxpref__, __set_auxpref__)
+85
View File
@@ -0,0 +1,85 @@
Overview
========
This document describes the IDAPython linking process used on Apple Silicon Macs.
Motivation
==========
Since IDAPython must be compatible with different Python versions, we must provide the user with
a mechanism to easily switch between them. Traditionally the approach on Mac was to have the
idapyswitch utility patch the libpython load commands in all of IDAPython's modules.
However this gets us into trouble on Apple Silicon, because codesigning rules are strictly enforced.
If we patch a dylib binary in IDA's installation, its code signature is invalidated and macOS will
refuse to load it (not only that, but the process is immediately killed).
We must be able to switch between various Python versions _without_ modifying IDA's binaries.
TBD Files
=========
This is where .tbd files can help us.
A .tbd file is a stub library that can be used in place of a real dylib. It is essentially just a text file
that describes the contents of a given library - e.g. the target arch, all exported symbols, and (most importantly)
the library's install name.
This allows us to configure the libpython install name used when our IDAPython binaries are linked, so that they
point to a symlink for libpython instead of the real libpython binary. Thus, it is trivial to switch between
different Python versions because need only to modify the symlink target, and all of IDAPython's modules can
remain untouched.
Generating TBD Files
====================
.tbd files can be generated using the 'tapi' utility on macOS. It is usually found here:
/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:
$ alias tapi='/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/tapi'
$ cp /Library/Frameworks/Python.framework/Versions/3.9/Python /tmp/
$ tapi stubify /tmp/Python
$ mv /tmp/Python.tbd ~/idasrc/current/plugins/idapython/libpython3.tbd
Then replace the following line:
install-name: '/Library/Frameworks/Python.framework/Versions/3.9/Python'
With:
install-name: '@executable_path/libpython3.link.dylib'
Note that the libpython3.link.dylib symlink will be created by idapyswitch at idapython build time
(see TBD_MODULE_DEP in idapython/makefile and pyver_tool_t::do_apply_version() in idapyswitch_mac.cpp).
It is also a good idea to clean up the .tbd file by removing all config directives that aren't
absolutely necessary. This makes it more likely that the .tbd file will continue to be compatible
with newer versions of the macOS linker (no surprise, the format is really unstable).
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>
...
Everything else can be removed.
Python 2
========
The same approach can be used for Python2, but instead use:
$ cp /System/Library/Frameworks/Python.framework/Versions/2.7/Python /tmp/
and use this install name instead:
install-name: '@executable_path/libpython2.link.dylib'
+4
View File
@@ -387,6 +387,9 @@ def check_python(args):
"structplace_t" : { "mustinherit" : "place_t" },
"textctrl_info_t" : { "mustinherit" : "ida_idaapi.py_clinked_object_t" },
"udt_type_data_t" : { "mustinherit" : "udtmembervec_t" },
"call_stack_t" : { "mustinherit" : "call_stack_info_vec_t" },
"abstract_graph_t" : { "mustinherit" : "ida_gdl.gdl_graph_t" },
"mutable_graph_t" : { "mustinherit" : "abstract_graph_t" },
# Just look for the presence of those things
"BADNODE" : {},
@@ -421,6 +424,7 @@ def check_python(args):
# "vivl_t" : { "mustinherit" : "ivl_t" },
"ivl_t" : { "mustinherit" : "uval_ivl_t" },
"ivlset_t" : { "mustinherit" : "uval_ivl_ivlset_t" },
"simple_graph_t" : { "mustinherit" : "ida_gdl.gdl_graph_t" },
}
types_coherence = types_coherence_base.copy()
+48 -7
View File
@@ -721,16 +721,20 @@ SWIGINTERN PyObject *_maybe_byte_array_as_hex_or_none_result(
//-------------------------------------------------------------------------
// OUT qstrvec_t
//-------------------------------------------------------------------------
%typemap(in,numinputs=0) qstrvec_t *out (qstrvec_t temp) {
$1 = &temp;
%typemap(in,numinputs=0) qstrvec_t *out (qstrvec_t temp)
{
// %typemap(in,numinputs=0) qstrvec_t *out (qstrvec_t temp)
$1 = &temp;
}
%typemap(argout) qstrvec_t *out
{
// %typemap(argout) qstrvec_t *out
Py_XDECREF(resultobj);
resultobj = qstrvec2pylist(*($1));
}
%typemap(freearg) qstrvec_t* out
{
// %typemap(freearg) qstrvec_t* out
// Nothing. We certainly don't want 'temp' to be deleted.
}
@@ -816,6 +820,13 @@ SWIGINTERN PyObject *_maybe_byte_array_as_hex_or_none_result(
%typemap(in) qtime64_t "$1 = PyLong_AsUnsignedLongLong($input);"
%typemap(out) qtime64_t "$result = PyLong_FromUnsignedLongLong($1);"
%typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) ea_t
{
// %typemap(typecheck, precedence=SWIG_TYPECHECK_STRING_ARRAY) ea_t
uint64 $1_temp;
$1 = PyW_GetNumber($input, &$1_temp);
}
//---------------------------------------------------------------------
// IN/OUT qstring/bytevec_t
//---------------------------------------------------------------------
@@ -1479,17 +1490,17 @@ SWIGINTERN PyObject *qstrvec2pylist(const qstrvec_t &vec)
}
//-------------------------------------------------------------------------
%define %uint_result_as_output(TYPE, CONVFUNC)
%typemap(in,numinputs=0) TYPE *result (TYPE temp)
%define %_uint_result_as_output(TYPE, CONVFUNC, CHECK_EXPR)
%typemap(in,numinputs=0) TYPE *result (TYPE temp = 0)
{
// %uint_result_as_output(TYPE, CONVFUNC) %typemap(in,numinputs=0) TYPE *result
// %_uint_result_as_output(TYPE, CONVFUNC, CHECK_EXPR) %typemap(in,numinputs=0) TYPE *result
$1 = &temp;
}
%typemap(argout) TYPE *result
{
// %uint_result_as_output(TYPE, CONVFUNC) %typemap(argout) TYPE *result
// %_uint_result_as_output(TYPE, CONVFUNC) %typemap(argout) TYPE *result
Py_XDECREF(resultobj);
if ( int(result) > 0 )
if ( CHECK_EXPR )
{
resultobj = CONVFUNC(*(TYPE *) $1);
}
@@ -1500,10 +1511,18 @@ SWIGINTERN PyObject *qstrvec2pylist(const qstrvec_t &vec)
}
}
%enddef
//-------------------------------------------------------------------------
%define %uint_result_as_output(TYPE, CONVFUNC)
%_uint_result_as_output(TYPE, CONVFUNC, int(result) > 0);
%enddef
%uint_result_as_output(uint32, PyLong_FromUnsignedLong);
%uint_result_as_output(uint64, PyLong_FromUnsignedLongLong);
%uint_result_as_output(int64, PyLong_FromLongLong);
%apply uint32 *result { uint32 *out };
%apply uint64 *result { uint64 *out };
%apply int64 *result { int64 *out };
#ifdef __EA64__
%apply uint64 *result { ea_t *result };
#else
@@ -1788,5 +1807,27 @@ ${ALL_IMPORTS}
// typemaps.
${NONNULL_TYPEMAPS}
// gdl_graph_t & subclasses
%cstring_output_maxstr_none(char *iobuf, int iobufsize);
%typemap(argout) (char *iobuf, int iobufsize)
{
// %typemap(argout) (char *iobuf, int iobufsize)
qfree($1);
}
%typemap(directorout) char *get_node_label (qstring tmp)
{
// %typemap(directorout) char *get_node_label (qstring tmp)
if ( IDAPyStr_AsUTF8(&tmp, result) )
::qstrncpy(iobuf, tmp.c_str(), iobufsize);
else
Swig::DirectorTypeMismatchException::raise(
SWIG_ErrorType(SWIG_TypeError),
"in output value of type 'char *' in method '$symname'");
$result = iobuf;
}
#endif // __HEADER_I__
// END: auto-inserted header
+147
View File
@@ -0,0 +1,147 @@
[epydoc]
# The list of objects to document. Objects can be named using
# dotted names, module filenames, or package directory names.
# Aliases for this option include "objects" and "values".
modules: idc, idautils, idaapi, ida_hexrays ida_allins ida_auto ida_bitrange ida_bytes ida_dbg ida_diskio ida_dirtree ida_entry ida_enum ida_expr ida_fixup ida_fpro ida_frame ida_funcs ida_gdl ida_graph ida_ida ida_idaapi ida_idc ida_idd ida_idp ida_ieee ida_kernwin ida_lines ida_loader ida_moves ida_nalt ida_name ida_netnode ida_offset ida_pro ida_problems ida_range ida_registry ida_search ida_segment ida_segregs ida_strlist ida_struct ida_tryblks ida_typeinf ida_ua ida_xref
# The type of output that should be generated. Should be one
# of: html, text, latex, dvi, ps, pdf.
output: html
# The path to the output directory. May be relative or absolute.
target: hr-html/
# An integer indicating how verbose epydoc should be. The default
# value is 0; negative values will supress warnings and errors;
# positive values will give more verbose output.
verbosity: 0
# A boolean value indicating that Epydoc should show a tracaback
# in case of unexpected error. By default don't show tracebacks
debug: 0
# If True, don't try to use colors or cursor control when doing
# textual output. The default False assumes a rich text prompt
simple-term: 0
### Generation options
# The default markup language for docstrings, for modules that do
# not define __docformat__. Defaults to epytext.
docformat: epytext
# Whether or not parsing should be used to examine objects.
parse: yes
# Whether or not introspection should be used to examine objects.
introspect: yes
# Don't examine in any way the modules whose dotted name match this
# regular expression pattern.
#exclude
# Don't perform introspection on the modules whose dotted name match this
# regular expression pattern.
#exclude-introspect
# Don't perform parsing on the modules whose dotted name match this
# regular expression pattern.
#exclude-parse
# The format for showing inheritance objects.
# It should be one of: 'grouped', 'listed', 'included'.
inheritance: listed
# Whether or not to inclue private variables. (Even if included,
# private variables will be hidden by default.)
private: no
# Whether or not to list each module's imports.
imports: no
# Whether or not to include syntax highlighted source code in
# the output (HTML only).
sourcecode: no
# Whether or not to includea a page with Epydoc log, containing
# effective option at the time of generation and the reported logs.
include-log: no
### Output options
# The documented project's name.
name: IDAPython
# The CSS stylesheet for HTML output. Can be the name of a builtin
# stylesheet, or the name of a file.
css: white
# The documented project's URL.
url: http://code.google.com/p/idapython/
# HTML code for the project link in the navigation bar. If left
# unspecified, the project link will be generated based on the
# project's name and URL.
link: <a href="http://www.hex-rays.com/">Hex-Rays</a>
# The "top" page for the documentation. Can be a URL, the name
# of a module or class, or one of the special names "trees.html",
# "indices.html", or "help.html"
#top: os.path
# An alternative help file. The named file should contain the
# body of an HTML file; navigation bars will be added to it.
#help: my_helpfile.html
# Whether or not to include a frames-based table of contents.
frames: yes
# Whether each class should be listed in its own section when
# generating LaTeX or PDF output.
separate-classes: no
### API linking options
# Define a new API document. A new interpreted text role
# will be created
#external-api: epydoc
# Use the records in this file to resolve objects in the API named NAME.
#external-api-file: epydoc:api-objects.txt
# Use this URL prefix to configure the string returned for external API.
#external-api-root: epydoc:http://epydoc.sourceforge.net/api
### Graph options
# The list of graph types that should be automatically included
# in the output. Graphs are generated using the Graphviz "dot"
# executable. Graph types include: "classtree", "callgraph",
# "umlclass". Use "all" to include all graph types
#graph: classtree
# The path to the Graphviz "dot" executable, used to generate
# graphs.
#dotpath: /usr/local/bin/dot
# The name of one or more pstat files (generated by the profile
# or hotshot module). These are used to generate call graphs.
#pstat: profile.out
# Specify the font used to generate Graphviz graphs.
# (e.g., helvetica or times).
graph-font: Helvetica
# Specify the font size used to generate Graphviz graphs.
#graph-font-size: 10
### Return value options
# The condition upon which Epydoc should exit with a non-zero
# exit status. Possible values are error, warning, docstring_warning
#fail-on: error
+1 -24
View File
@@ -22,7 +22,7 @@ try:
except:
from io import StringIO
ignore_types = (int, float, str, bool, dict, list, tuple, types.ModuleType)
ignore_types = (int, float, str, bool, dict, list, tuple, bytes, types.ModuleType)
TRANSLATED_MARKER = b"\xE2\x86\x97"
if sys.version_info.major < 3:
@@ -298,23 +298,6 @@ all_specific_translations = {
"Helper for pickle.",
), "helper for pickle", False),
],
#
# The following is a kludge: IDA 7.5 ships with
# release_pydoc_injections*.txt and ida_nalt.py files that have
# a very slightly different wrapping. We want to prevent this
# from building IDAPython under the SDK.
#
"ida_nalt.set_outfile_encoding_idx" : [
((
"the encoding index idx can be 0 to use the IDB's default 1",
"the encoding index idx can be 0 to use the IDB's default",
), "<snipped>", False ),
((
"1-byte-per-unit encoding (C++: int)",
"-byte-per-unit encoding (C++: int)",
), "<snipped>", False ),
],
}
if is_64:
@@ -339,12 +322,6 @@ def dump_namespace(namespace, namespace_name, keys, vec_info=None):
if should_ignore_name(thing_name):
continue
thing = getattr(namespace, thing_name)
# KLUDGE
if thing_name == "IDB_Hooks":
try:
del thing.dirtree_segm_moved
except:
pass
if isinstance(thing, ignore_types):
continue
if thing in spotted_things:
+235
View File
@@ -0,0 +1,235 @@
<html>
<head>
<meta charset="UTF-8">
<title>IDAPython examples</title>
<script type="text/javascript">
collapse_normal = "data:image/png;base64,"
+"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgI"
+"fAhkiAAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAE9JREFUSIntz8EJwFAIA9AY"
+"upiTtX8wwcm01/YW+JcWfEeJGIExxv+ZEoqIS8mRTHfP5+yQWpidSq6qAOB1"
+"gMriDumD7l5KjmRutRljfNQNRgQNjM3h6lA=";
collapse_hover = "data:image/png;base64,"
+"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgI"
+"fAhkiAAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAbVJREFUSInVlT1v01AUhp/3"
+"ioUoEiOIAl2QWDpCB4qIbKfZGPgB/AXE1ERiyYSo+BcsLAxVw4avrEgoUkBM"
+"UKEKsUbKxpjB9WGgRWnspLcuS9/x6Ph5fK4/Dlz2KLRxMBg0ms1mx8wi4BbQ"
+"AKbAAbAfx/FhLcFoNLo6m81eAF3g2opWD3TjOP4aLPDer0naA+6fdSPHOZL0"
+"Moqi3TMFWZbdMLMxcCcQ/i+SeicSV9XQ7/edmb2vAwcws1dpmm7Dkgm8988k"
+"va0Dn8uhpI3KCSTtXBAOcK8oiiclQZZld4GN/yBA0tMri0Uz26yo7S7WlgAf"
+"AVtzpc0qwU3p9KNJkqQXIvDe9yXNC9ZKR+ScsxBYYIrSBEVRTBYnyLKsG0Iz"
+"s62F0qQkAD5XXPg6RFCRcemIkiT5ZWbfagJPRdJe5XfgnAt6a1bFzH4AHyoF"
+"w+HwHfDpAvwj59zzKIrypT+7NE2vO+fGwHoNwU4cx29gyc8OoN1uT/M8fyjp"
+"yznAuaTeCXylAKDT6UyAx/xdNr9X9Ur6KOnB/C6Ac6zM4822LSkys9uSGkVR"
+"TJ1z351z+61W62co63LlD5ogjVIofsWl";
expand_normal = "data:image/png;base64,"
+"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgI"
+"fAhkiAAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAKpJREFUSIntk9ERgjAMhr/0"
+"HMANdARGIF3EUdRNXIQrbsAKbsAExBfg0FMsVR686/eUNvkvaZJCJvMtslQQ"
+"QtgCRX9sVbWZi98kFFWYWejtK1DOBbuEBItYPUHUDKqqOo0CkT1wADCzG3AZ"
+"fM65WlXrqTZqBiJyfHO/A0Zf13UADwlWb1HUC8zsPNifWvSsTfkH5XRNvffl"
+"XPz/r2nKT25ERHu7/WUxmcxr7pBbLDAu4/t2";
expand_hover = "data:image/png;base64,"
+"iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgI"
+"fAhkiAAAAAlwSFlzAAAWJQAAFiUBSVIk8AAAAgxJREFUSInVlbFrFFEQxn/z"
+"2MbjQOQKLUwCYiUiiJgm4c59exErwVLwP7AREc/OrcSQUvAfsEgjiLnydnm5"
+"5iBCKo0gokWQwHEHsbC44m7H5k73cruXjdjkg4XHzDfzzZt9bx6cdkhRYrPZ"
+"LJXL5duq6gMXgRLQBfaALWvtl38S6HQ6ZwaDwSOgAZydQ42BhrV2t7BAu91e"
+"GA6H70Xk+nGFjDFU1cdBELw6VsA5d0FVd4DFgsn/QESe+b6/DmCyCGEYGlV9"
+"m5P8EIjG326GH1V9EUXRGuTswDn3QFXf5BS4ba31x7xbqupyeJ/7/f61zB2o"
+"aiMn6CS4UqlU7s4IOOcuA1f/gwAics87alTV5Qzbeiro+2Q9Go32RSTtWwVW"
+"UqHLM/8gjuMnIrKRtllrC13IOI5DEXmeMv2aaZExRoskK4hkpkVJkhyITBfs"
+"nGuk/PtBEGwCtFqtRc/z7k98qrrCNA5mBIAPRw2q+nKyFpFtYBPA87xLaV9W"
+"rpkWBUHwTVU/zgkqDBF5l3kPRGReVUWx1+v1mpmnIwxDU61W28BqhvuQvyPi"
+"HHAjgzMSkTu+70e5xy+KovPGmB1g6YSVAzy11m5AzrADqNfr3fHFyRxoORgC"
+"DyfJ5woA+L7/YyzSAH7O44pIS0RuWmtfT9mLljZ+2dZExFfVBREpJUnSNcZ8"
+"MsZs1Wq1r0VznS78BtXqtYTFW0oe";
var name_expanded = null;
function is_expanded()
{
return name_expanded != null;
}
function set_expanded(name)
{
name_expanded = name;
}
function init()
{
set_all_images("c_expand_gadget", expand_normal);
}
function image_with_hover(name)
{
set_image(name, name == name_expanded ? collapse_hover : expand_hover);
}
function image_without_hover(name)
{
set_image(name, name == name_expanded ? collapse_normal : expand_normal);
}
function expand_click(name)
{
if ( is_expanded() && name_expanded != name )
{
// something else is expanded - close it
expand_toggle(name_expanded);
}
expand_toggle(name, true);
}
function expand_toggle(name, cursor_is_there=false)
{
set_expanded(is_expanded() ? null : name);
if ( cursor_is_there )
image_with_hover(name);
else
image_without_hover(name);
// actual expansion / collapse
var div = document.getElementById('DIV_' + name);
div.style.display = is_expanded() ? 'initial' : 'none';
// scroll a little for divs at the bottom of the page
if ( is_expanded() )
{
var margin = 100;
var rect = div.getBoundingClientRect();
var delta = rect.top + margin - window.innerHeight;
//console.log('rect.top = ' + rect.top);
//console.log('window.innerHeight = ' + window.innerHeight);
//console.log('delta = ' + delta);
if ( delta > 0 )
window.scrollBy(0, delta);
}
}
function on_see_also(see_also)
{
if ( is_expanded() )
{
// likely it is, since I clicked on "see also";
// close it
expand_toggle(name_expanded);
}
expand_toggle(see_also);
document.getElementById('IMG_' + see_also).scrollIntoView();
return true;
}
function set_image(name, source)
{
document.getElementById('IMG_' + name).src = source;
}
function set_all_images(classname, source)
{
var all = document.getElementsByClassName(classname);
for ( var i in all )
all[i].src = source;
}
function gotoMD()
{
location.href = "https://github.com/idapython/src/blob/master/examples/index.md";
}
</script>
</head>
<body onload="init();">
<div style="margin:20px 20px 50px 20px">
<span style="border:solid black 1px;padding:10px;font-size:small;cursor:pointer" onclick="gotoMD();">
Switch to MarkDown</span>
</div>
<h1>IDAPython examples:</h1>
<!--gen:group:category-->
<h2>Category: <!--gen:category--></h2>
<div class="c_list">
<!--gen:block-->
<a name="<!--gen:name-->"/>
<div>
<img id="IMG_<!--gen:name-->" class="c_expand_gadget"
onmouseover="image_with_hover('<!--gen:name-->');"
onmouseout="image_without_hover('<!--gen:name-->');"
onclick="expand_click('<!--gen:name-->');"/>
<!--gen:name-->: <i><!--gen:summary--></i>
</div>
<div id="DIV_<!--gen:name-->" style="display:none">
<hr/>
<h2><!--gen:name--></h2>
<h3>Category</h3>
<indent><!--gen:category--></indent>
<h3>Summary</h3>
<indent><!--gen:summary--></indent>
<h3>Source code</h3>
<indent><a target="_blank"
  href="https://github.com/idapython/src/blob/master/examples/<!--gen:path-->">
Jump to GitHub</a></indent>
<h3>Description</h3>
<indent>
<pre>
<!--gen:description-->
</pre>
</indent>
<!-- "Keywords" heading produced only if there is data for it -->
<!--gen:block-->
<!--gen:first-->
<h3>Keywords</h3>
<!--gen:end-->
<span><!--gen:keywords--></span>
<!--gen:end-->
<h3>Uses</h3>
<ul>
<!--gen:block-->
<li><!--gen:uses--></li>
<!--gen:end-->
</ul>
<!-- "See also" heading produced only if there is data for it -->
<!--gen:block-->
<!--gen:first-->
<h3>See also</h3>
<ul>
<!--gen:end-->
<li><a href="#<!--gen:see_also-->"
onclick="on_see_also('<!--gen:see_also-->');">
<!--gen:see_also--></a></li>
<!--gen:last-->
</ul>
<!--gen:end-->
<!--gen:end-->
<hr/>
</div>
<!-- end block (per example in this category) -->
<!--gen:end-->
</div>
<!-- end group by category -->
<!--gen:end-->
</body>
</html>
+44
View File
@@ -0,0 +1,44 @@
[Switch to HTML](http://htmlpreview.github.io/?https://github.com/idapython/src/blob/master/examples/index.html)
# IDAPython examples
<!--gen:group:category-->
## Category: <!--gen:category-->
<!--gen:block-->
#### <!--gen:name-->
<details>
<summary><!--gen:summary--></summary>
<blockquote>
#### Source code
<a href="https://github.com/idapython/src/blob/master/examples/<!--gen:path-->"><!--gen:path--></a>
#### Category
<!--gen:category-->
#### Description
<!--gen:description-->
#### Keywords
<!--gen:block-->
<!--gen:keywords-->
<!--gen:end-->
#### Uses
<!--gen:block-->
* <!--gen:uses-->
<!--gen:end-->
#### See also
<!--gen:block-->
* [<!--gen:see_also-->](#<!--gen:see_also-->)
<!--gen:end-->
</blockquote>
</details>
<!--gen:end-->
<!--gen:end-->
+560
View File
@@ -0,0 +1,560 @@
"""
Generate the index.html for the examples subdirectory,
based on structured docstrings on each Python example
"""
from __future__ import print_function
import ast
import re
import os
import sys
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("-e", "--examples-dir", required=True)
parser.add_argument("-t", "--template", required=True)
parser.add_argument("-o", "--output", required=True)
parser.add_argument("-v", "--verbose", default=False, action="store_true")
args = parser.parse_args()
def verb(msg):
if args.verbose:
print(msg)
class ProcessException(Exception):
pass
#-------------------------------------------------------------------------------
class Examples(object):
def __init__(self):
self.re_indent = re.compile(r'^ *')
self.re_tag = re.compile(r'^ *([a-zA-Z_][a-zA-Z_0-9]*):')
self.tags = Tags()
self.html = None
def template(self, path):
with open(path, 'r') as f:
self.html = HTML(f.read(), self.tags)
def process(self):
if not self.html:
raise ProcessException('No template!')
self.examples = []
for relpath, path in self._files_with_extension('.py', args.examples_dir):
verb("Processing \"%s\"" % path)
with open(path, 'r') as f:
self._load_ast(relpath, path, ast.parse(f.read(), path))
self.examples = {'sub': sorted(self.examples, \
key=lambda x: x[self.tags.order()])}
self.html.produce(self.examples)
def _load_ast(self, relpath, path, tree):
self.tags.reset()
self.tags.add(Tags.PATH, relpath)
self.tags.add(Tags.NAME, os.path.splitext(os.path.basename(path))[0])
self.tags.add(Tags.USES, self._uses_names(tree))
self.tags.add(Tags.CATEGORY, relpath.split(os.sep)[0])
self._parse_structured_comment(ast.get_docstring(tree, False))
self.examples.append(self.tags.get())
def _parse_structured_comment(self, docstring):
if not docstring:
return
first_line = True
group_tag = None
group_lines = []
def end_group():
if group_tag:
self._remove_common_indentation(group_lines)
if group_tag == Tags.DESCRIPTION:
item = '\n'.join(group_lines).lstrip('\n')
elif group_tag in (Tags.KEYWORDS, Tags.SEE_ALSO):
item = [{group_tag: x.strip()} \
for x in ','.join(group_lines).split(',')]
else:
item = ' '.join(group_lines)
self.tags.add(group_tag, item)
# Blocks of lines are separated by an empty line.
# An attempt is made to preserve the original indentation
# of each block of lines.
#
# If a block of lines wishes to contain a blank line,
# it must represent it with a line containing only a dot ('.')
# (indentation is irrelevant for these 'dot' lines).
# Example:
# description:
# This is one
# big paragraph
# .
# This is another
# big paragraph
# .
# This is the final
# big paragraph
warned = False
for line in docstring.split('\n'):
indent, line = self._indented_line(line.rstrip(), 0)
if line == '':
end_group()
first_line = True
group_tag = None
group_lines = []
continue
if first_line:
first_line = False
m = self.re_tag.match(line)
if not m:
if not warned:
warned = True
path = self.tags.get()[Tags.PATH]
verb('{}:\n No tag in docstring'.format(path))
continue
group_tag = m.group(1)
if not self.tags.is_valid(group_tag) or \
not self.tags.can_occur_in_docstring(group_tag):
path = self.tags.get()[Tags.PATH]
msg = self.tags.error_message(group_tag)
verb('{}:\n {}'.format(path, msg))
group_tag = None
indent, line = self._indented_line(line, m.end())
if group_tag:
group_lines.append( (indent, line) )
end_group()
def _indented_line(self, line, fromPos):
line = line[fromPos:]
m = self.re_indent.match(line)
indent = fromPos + len(m.group())
line = line[m.end():]
if line == '.':
return None, None
return indent, line
def _remove_common_indentation(self, lines):
if not lines:
return
min_indent = min(t[0] for t in lines if t[1])
for i in range(len(lines)):
if lines[i][1]:
lines[i] = ((lines[i][0] - min_indent) * ' ') + lines[i][1]
else:
lines[i] = ''
def _uses_names(self, tree):
names = set()
def callback(name):
names.add(name)
visitor = TreeVisitor(callback, ['idc', 'idautils'])
visitor.generic_visit(tree)
return [{Tags.USES: name} for name in sorted(names)]
def _files_with_extension(self, ext, rootdir):
for path, _, files in os.walk(rootdir):
for filename in files:
if os.path.splitext(filename)[1] == ext:
relpath = os.path.relpath(path, rootdir)
yield os.path.join(relpath, filename), \
os.path.join(path, filename)
#-------------------------------------------------------------------------------
class Tags(object):
NAME = "name"
PATH = "path"
SUMMARY = "summary"
DESCRIPTION = "description"
CATEGORY = "category"
KEYWORDS = "keywords"
USES = "uses"
SEE_ALSO = "see_also"
JSDATA = "jsdata"
# tags that can be used in the template (as a <!--gen:xxx--> comment)
ALL_TAGS = set([NAME, PATH, SUMMARY, DESCRIPTION, CATEGORY, \
KEYWORDS, USES, SEE_ALSO, JSDATA])
# tags that can be used in the examples' docstrings
IN_DOCSTRING = set([SUMMARY, DESCRIPTION, CATEGORY, \
KEYWORDS, USES, SEE_ALSO])
def __init__(self):
self.tags = {}
self.reset()
def order(self):
return self.NAME
def error_message(self, name):
return 'Unrecognized tag: "{}"'.format(name)
def check(self, name):
if name not in self.ALL_TAGS:
raise ProcessException(self.error_message(name))
def is_valid(self, name):
return name in self.ALL_TAGS
def can_occur_in_docstring(self, tag):
return tag in self.IN_DOCSTRING
def reset(self):
self.items = {}
for tag in self.ALL_TAGS:
if tag in (self.KEYWORDS, self.USES, self.SEE_ALSO):
self.items[tag] = []
elif tag != self.JSDATA:
self.items[tag] = ''
def add(self, tag, item):
self.items[tag] = item
def get(self):
return self.items
#-------------------------------------------------------------------------------
class TreeVisitor(ast.NodeVisitor):
def __init__(self, callback, interesting_names, *args):
super(TreeVisitor, self).__init__(*args)
self.my_callback = callback
self.interesting_names = set(interesting_names)
def visit_ImportFrom(self, node):
if self._is_interesting(node.module):
self._add_interesting_names(node.names)
def _add_interesting_names(self, aliases):
for alias in aliases:
if isinstance(alias, ast.alias):
name = alias.asname if alias.asname else alias.name
self.interesting_names.add(name)
def _is_interesting(self, name):
return name.startswith('ida_') or name in self.interesting_names
def visit_Name(self, node):
self._callback_if_interesting(node)
def visit_Attribute(self, node):
self._callback_if_interesting(node)
def _callback_if_interesting(self, node):
names = self._dotted_name(node)
if not names:
return
if self._is_interesting(names[0]) \
and names[-1] != '__init__': # removed calls to base constructors
self.my_callback('.'.join(names))
def _dotted_name(self, node):
if isinstance(node, ast.Name):
return [node.id]
if isinstance(node, ast.Attribute):
names = self._dotted_name(node.value)
if names:
return names + [node.attr]
return None
#-------------------------------------------------------------------------------
class HTML(object):
def __init__(self, template, tags):
self.replacer = TemplateReplacer(tags)
self.replacer.template(template)
def produce(self, examples):
with open(args.output, 'w') as f:
self.replacer.expand(examples, f)
#-------------------------------------------------------------------------------
class SpecialBlock(object):
GROUP = 0
FIRST = 1
LAST = 2
def __init__(self, kind, payload=None):
self.kind = kind
self.payload = payload
#-------------------------------------------------------------------------------
class TemplateReplacer(object):
def __init__(self, tags):
self.tags = tags
self.re_variable = re.compile(r'(?i)<!--gen:([a-z_]+)-->')
self.comment_block = '<!--gen:block-->'
self.comment_end = '<!--gen:end-->'
self.comment_group = re.compile(r'<!--gen:group:([a-z_]+)-->$')
self.comment_first = '<!--gen:first-->'
self.comment_last = '<!--gen:last-->'
def template(self, content):
lines = content.strip().split('\n')
# convert the file content, with block-end repetition blocks,
# into a list of (1) strings and (2) nested lists for blocks
stack = [[]]
for line in lines:
clean = line.strip().lower()
if clean == self.comment_block:
stack.append([])
elif clean == self.comment_end:
if len(stack) == 0:
raise ProcessException('mismatched gen:end')
d = stack.pop()
stack[-1].append(d)
elif clean == self.comment_first:
# open block
stack.append([SpecialBlock(SpecialBlock.FIRST)])
elif clean == self.comment_last:
# open block
stack.append([SpecialBlock(SpecialBlock.LAST)])
else:
m = self.comment_group.match(clean)
if m:
v = m.group(1)
self.tags.check(v)
# open block
stack.append([SpecialBlock(SpecialBlock.GROUP, v)])
else:
stack[-1].append(line)
self.template = stack.pop()
if len(stack) != 0:
raise ProcessException('gen:block/group without gen:end')
def expand(self, data, f):
self._expand(self.template, data, None, f)
def _expand(self, block, data, conditions, f):
self._verify_block(block, data)
if not isinstance(block, list):
raise ProcessException('Expected block')
for line in block:
if isinstance(line, list):
first = False # meaning, restrict/show only the first
last = False
if line and isinstance(line[0], SpecialBlock):
special = line[0]
line = line[1:]
if special.kind == SpecialBlock.GROUP:
gvar = special.payload
subkey = 'sub'
elif special.kind == SpecialBlock.FIRST:
first = True
subkey = None
elif special.kind == SpecialBlock.LAST:
last = True
subkey = None
else:
raise ProcessException('Unknown SpecialBlock: {} {}' \
.format(special.kind,
repr(special.payload)))
else:
# regular block
gvar = None
subkey = self._obtain_subkey(line)
if subkey is None:
# (i.e. first,last): multiple lines but no data repetition
if conditions:
if first and not conditions[0]:
continue
if last and not conditions[1]:
continue
self._expand(line, data, None, f)
continue
subdata = data[subkey]
if not isinstance(subdata, list):
raise ProcessException('Expected multiple data for {}' \
.format('group' if gvar else 'block'))
# repeat for each item
if gvar:
subdata = self._group_by(subdata, gvar)
n_items = len(subdata)
for i in range(n_items):
conditions = i == 0, i == n_items - 1
self._expand(line, subdata[i], conditions, f)
continue
f.write(self._substitute_variables(line, data))
f.write('\n')
def _obtain_subkey(self, block):
# presently (we don't need more at the moment)
# a block contains either:
# - a single variable inside, under the key = variable
# - multiple variables, under a constant key = 'sub'
# (so just one per block)
variables = set()
for line in block:
if isinstance(line, list):
continue # only this level
for key, _, _ in self._variables_in_line(line):
variables.add(key)
for key in variables:
break # get first
return key if len(variables) == 1 else 'sub'
def _group_by(self, data, gvar):
# data assumed already sorted
grouped = {}
for item in data:
value = item[gvar]
if isinstance(value, list):
for obj in value:
subvalue = obj[gvar]
if subvalue not in grouped:
grouped[subvalue] = []
grouped[subvalue].append(item)
else:
if value not in grouped:
grouped[value] = []
grouped[value].append(item)
return [{gvar: key, 'sub': grouped[key]} for key in sorted(grouped)]
def _substitute_variables(self, line, data):
out = ''
last = 0
for key, start, end in self._variables_in_line(line):
sub = self._substitution_string(key, data)
out += line[last:start] + sub
last = end
out += line[last:]
return out
def _substitution_string(self, key, data):
if key != Tags.JSDATA:
value = data[key]
if key == Tags.PATH:
value = "/".join(value.split(os.sep))
return str(value)
if 'sub' not in data:
ProcessException('Please use <!--gen:{}--> at the top level only' \
.format(Tags.JSDATA))
data = data['sub']
# JavaScript representation of the data
js = '// collected data\nexamples = ['
first = True
for item in data:
if first:
first = False
else:
js += ','
js += '\n' + self._js_example(item)
js += '\n];'
return js
def _js_example(self, data):
first = True
js = '{'
for tag in Tags.ALL_TAGS:
if tag in data and data[tag]:
if first:
first = False
else:
js += ','
js += "'" + tag + "': " + self._js_subdata(tag, data[tag])
js += '}'
return js
def _js_subdata(self, tag, subdata):
if isinstance(subdata, list):
# no need to recurse, these are object enclosing a single item
subdata = [x[tag] for x in subdata]
return repr(subdata)
def _verify_block(self, block, data):
# check that all variables at the first 'flat' level of this block
# are present in the data and are not sublists
# (which would require an inner block)
for line in block:
if isinstance(line, list):
continue # check only the flat level
for key, _, _ in self._variables_in_line(line):
if key == Tags.JSDATA:
continue
if key not in data:
raise ProcessException('No keyword "{}" in data' \
.format(key))
if isinstance(data[key], list):
raise ProcessException('Missing block for multiple "{}" data' \
.format(key))
def _variables_in_line(self, line):
pos = 0
while True:
m = self.re_variable.search(line, pos)
if m is None:
break
tag = m.group(1).lower()
self.tags.check(tag)
yield tag, m.start(), m.end()
pos = m.end()
try:
e = Examples()
e.template(args.template)
e.process()
except ProcessException as ex:
print('? {}\n {}'.format(sys.argv[0], ex))
sys.exit(1)
# other exceptions - let them fail
+2 -2
View File
@@ -7,8 +7,8 @@ recipe = {
},
"create_hint" : {
"params" : {
"result_hint" : { "suppress_for_call" : True, },
"implines" : { "suppress_for_call" : True, },
"hint" : { "suppress_for_call" : True, },
"important_lines" : { "suppress_for_call" : True, },
},
"return" : {
"type" : "PyObject *",
-1
View File
@@ -14,7 +14,6 @@ recipe = {
{ "name" : "cid", "type" : "const_t" },
],
},
"dirtree_segm_moved" : {"ignore" : True},
}
default_rtype = "void"
+1
View File
@@ -5,6 +5,7 @@ recipe = {
"ev_last_cb_before_type_callbacks" : {"ignore" : True},
"ev_get_idd_opinfo" : {"ignore" : True},
"ev_loader_elf_machine" : {"ignore" : True},
"ev_broadcast" : {"ignore" : True},
"ev_ana_insn" : {
"return" : {
"type" : "bool",

Some files were not shown because too many files have changed in this diff Show More