mirror of
https://github.com/idapython/src
synced 2026-06-08 14:47:00 +00:00
IDAPython for IDA 7.6
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
"""
|
||||
|
||||
@@ -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.
|
||||
|
||||
"""
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
"""
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+434
-82
File diff suppressed because it is too large
Load Diff
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
@@ -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,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,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,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,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,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,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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+2870
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
+2
-2
@@ -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
@@ -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];
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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 ]
|
||||
...
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+3678
-486
File diff suppressed because it is too large
Load Diff
+2
-2
@@ -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
@@ -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));
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
//<inline(py_ieee)>
|
||||
typedef bytevec_t bytevec12_t;
|
||||
typedef bytevec_t bytevec10_t;
|
||||
//</inline(py_ieee)>
|
||||
|
||||
@@ -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
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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)>
|
||||
|
||||
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+600
-80
File diff suppressed because it is too large
Load Diff
+4524
-442
File diff suppressed because it is too large
Load Diff
+4537
-462
File diff suppressed because it is too large
Load Diff
+9
-4
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)>
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
{
|
||||
ea_t start_ea;
|
||||
ea_t end_ea;
|
||||
|
||||
%pythoncode {
|
||||
use64 = is_64bit
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __EA64__
|
||||
|
||||
@@ -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"
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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__)
|
||||
|
||||
|
||||
@@ -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'
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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:
|
||||
|
||||
@@ -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>
|
||||
@@ -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-->
|
||||
Executable
+560
@@ -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
|
||||
@@ -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 *",
|
||||
|
||||
@@ -14,7 +14,6 @@ recipe = {
|
||||
{ "name" : "cid", "type" : "const_t" },
|
||||
],
|
||||
},
|
||||
"dirtree_segm_moved" : {"ignore" : True},
|
||||
}
|
||||
|
||||
default_rtype = "void"
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user