IDAPython 1.4.0 - IDA Pro 5.7 support

This commit is contained in:
elias.bachaalany 2010-06-28 12:36:40 +00:00
parent 5f2262fad9
commit 3a5063330c
40 changed files with 20591 additions and 15275 deletions

View File

@ -1,63 +1,60 @@
---------------------------------------------------------- ----------------------------------------------------------
IDAPython - Python plugin for Interactive Disassembler Pro IDAPython - Python plugin for Interactive Disassembler Pro
---------------------------------------------------------- ----------------------------------------------------------
Building From Source Building From Source
-------------------- --------------------
REQUIREMENTS REQUIREMENTS
------------ ------------
[Tested versions are in brackets] [Tested versions are in brackets]
- IDA and IDA SDK [5.6] - IDA and IDA SDK [5.6]
http://www.hex-rays.com/idapro/ http://www.hex-rays.com/idapro/
- Python [2.5.1, 2.6.1] - Python [2.5.1, 2.6.1]
http://www.python.org/ http://www.python.org/
- Simplified Wrapper Interface Generator (SWIG) [1.3.36] - Simplified Wrapper Interface Generator (SWIG) [1.3.36]
http://www.swig.org/ http://www.swig.org/
- Unix utilities (GNU patch on Windows): - Unix utilities (GNU patch on Windows):
http://www.research.att.com/sw/tools/uwin/ or http://www.research.att.com/sw/tools/uwin/ or
http://unxutils.sourceforge.net/ or http://unxutils.sourceforge.net/ or
http://www.cygwin.com/ http://www.cygwin.com/
- GCC on Linux and Mac OS X [4.0.1, 4.1.3] - GCC on Linux and Mac OS X [4.0.1, 4.1.3]
Comes with your distribution Comes with your distribution
- Microsoft Visual C on Windows [Microsoft Visual C++ 2008 Express Edition] - Microsoft Visual C on Windows [Microsoft Visual C++ 2008 Express Edition]
http://msdn.microsoft.com/vstudio/express/visualc/ http://msdn.microsoft.com/vstudio/express/visualc/
BUILDING BUILDING
-------- --------
Make sure all the needed tools (compiler, swig) are on the PATH. Make sure all the needed tools (compiler, swig) are on the PATH.
1, Unpack the IDAPython source and IDA Pro SDK into the following 1, Unpack the IDAPython source and IDA Pro SDK into the following
directory structure: directory structure:
swigsdk-versions/5.6/ - version 5.6 of the IDA Pro SDK swigsdk-versions/5.6/ - version 5.6 of the IDA Pro SDK
idapython/ - IDAPython source code idapython/ - IDAPython source code
2, On Mac OS X copy libida.dylib from the IDA install directory to 2, On Mac OS X copy libida.dylib from the IDA install directory to
swigsdk-versions/5.6/lib/gcc32.mac/ swigsdk-versions/5.6/lib/gcc32.mac/
and libida64.dylib to and libida64.dylib to
swigsdk-versions/5.6/lib/gcc64.mac/ swigsdk-versions/5.6/lib/gcc64.mac/
3, Build the plugin 3, Build the plugin
python build.py python build.py
It is possible to build the plugin for different Python versions by It is possible to build the plugin for different Python versions by
running build.py with the corresponding Python binary. running build.py with the corresponding Python binary.
Some build options: Run 'build.py --help' for more information.
--ea64: builds the 64-bit version
--no-early-load: builds the IDAPython plugin w/o PLUGIN_FIX plugin flag 4, Install the components as described in README.txt
(This flag disables the ability to write file loaders in IDAPython)
See build.py for build details and possible tweaks.
4, Install the components as described in README.txt
See build.py for build details and possible tweaks.

View File

@ -1,105 +1,117 @@
Please see http://code.google.com/p/idapython/source/list for a Please see http://code.google.com/p/idapython/source/list for a detailed list of changes.
detailed list of changes.
Changes from version 1.3.0 to 1.4.0
Changes from version 1.2.0 to 1.3.0 ------------------------------------
------------------------------------ - IDA Pro 5.7 support
- idaapi.cvar.cmd is now accessible via idapi.cmd instead
- IDA Pro 5.6 support - Python statement (Alt-8) is now 16kb long
- Added Appcall mechanism - Dropped script box and File/Python file. IDA has this functionality now.
- Added procregs to idautils.py (r254) - Refactored the code
- Lots of cleanups and fixes - It is possible to turn off script timeout
- All scripts are executed via 'IDAPython_ExecScript' (check idaapi.i)
Changes from version 1.1.0 to 1.2.0 - Added '--doc' switch to "build.py" script
------------------------------------ - Documented all manually wrapped functions (check 'pywraps' module in the docs)
- Lots of cleanups and fixes
- 64-bit support (largely untested)
- IDA Pro 5.5 support Changes from version 1.2.0 to 1.3.0
- Long running (or inifinitely looping) scripts can now be stopped ------------------------------------
- Host of IDC updates and fixes
- netnode.hpp is now mostly wrapped - IDA Pro 5.6 support
- idautils use generators instead of lists - Added Appcall mechanism
- Functions() and GetFchunkAttr() now work properly - Added procregs to idautils.py (r254)
- Lots of cleanups and fixes - Lots of cleanups and fixes
Changes from version 1.1.0 to 1.2.0
Changes from version 0.9.0 to 1.0.0 ------------------------------------
-----------------------------------
- 64-bit support (largely untested)
- Upgraded IDA Pro base version to 5.1 - IDA Pro 5.5 support
- Dropped Python 2.4 support - Long running (or inifinitely looping) scripts can now be stopped
- Mac OS X support - Host of IDC updates and fixes
- IDC compatibility layer is now complete and up to date for IDA 5.1 - netnode.hpp is now mostly wrapped
- INCOMPATIBLE CHANGE: the idaapi module needs to be imported manually - idautils use generators instead of lists
- Support for IDB and debug notification hooks - Functions() and GetFchunkAttr() now work properly
- Support for GUI hotkeys (see examples/hotkey.py) - Lots of cleanups and fixes
- Simple two-way calling mechanism between IDC and IDAPython
- Significantly better IDA API coverage
- Support for IDB and debug event hooks Changes from version 0.9.0 to 1.0.0
- get_current_instruction() deprecated, use the idaapi.cvar.cmd variable -----------------------------------
- Tons of IDC fixes
- Tons of other misc fixes - Upgraded IDA Pro base version to 5.1
- Dropped Python 2.4 support
- Mac OS X support
Changes from version 0.8.0 to 0.9.0 - IDC compatibility layer is now complete and up to date for IDA 5.1
----------------------------------- - INCOMPATIBLE CHANGE: the idaapi module needs to be imported manually
- Support for IDB and debug notification hooks
- Upgraded base version to IDA Pro 5.0 - Support for GUI hotkeys (see examples/hotkey.py)
- Works with IDA Pro 5.1 - Simple two-way calling mechanism between IDC and IDAPython
- Python 2.4 and 2.5 supported - Significantly better IDA API coverage
- Close to complete IDC compatbility layer (in sync with 4.9) - Support for IDB and debug event hooks
- Significatnly improved IDA SDK API covergage (see STATUS.txt for details) - get_current_instruction() deprecated, use the idaapi.cvar.cmd variable
- IDA SDK patch size reduced to less than half - Tons of IDC fixes
- Simplified installation (plugins.cfg modification not needed) - Tons of other misc fixes
- Evaluation window content is saved over IDA restarts (in the database)
- Windows version is built with Microsoft Visual C++ Express Edition
- Build makefile replaced with a Python script Changes from version 0.8.0 to 0.9.0
- Cleanups and small fixes -----------------------------------
- Upgraded base version to IDA Pro 5.0
Changes from version 0.7.0 to 0.8.0 - Works with IDA Pro 5.1
----------------------------------- - Python 2.4 and 2.5 supported
- Close to complete IDC compatbility layer (in sync with 4.9)
- Added support for IDA Pro 4.9 - Significatnly improved IDA SDK API covergage (see STATUS.txt for details)
- Dropped support for IDA Pro 4.7 - IDA SDK patch size reduced to less than half
- NOTE: Windows version is linked against Python 2.4. - Simplified installation (plugins.cfg modification not needed)
- New wrappers: search.hpp, dbg.hpp, loader.hpp, diskio.hpp, nalt.hpp - Evaluation window content is saved over IDA restarts (in the database)
- idc.py synced up to IDA 4.8 - Windows version is built with Microsoft Visual C++ Express Edition
- Added 38 IDC functions - Build makefile replaced with a Python script
- Fixed asklong(), askseg() and askaddr() - Cleanups and small fixes
- Automatically generated cross reference documentation (epydoc)
- User-specific init file support (see README,txt)
- Deprecated some functions that have direct Python equivalents (see idc.py) Changes from version 0.7.0 to 0.8.0
- Fixed exception in ScriptBox when invoked empty. -----------------------------------
- Lots of cleanups and small fixes
- Added support for IDA Pro 4.9
- Dropped support for IDA Pro 4.7
Changes from version 0.6.0 to 0.7.0 - NOTE: Windows version is linked against Python 2.4.
----------------------------------- - New wrappers: search.hpp, dbg.hpp, loader.hpp, diskio.hpp, nalt.hpp
- Batch execution support (use the option -OIDAPython:yourscript.py) - idc.py synced up to IDA 4.8
- Added ScriptBox - lists previously run scripts (Hotkey:Alt-7) - Added 38 IDC functions
- Added support for IDA Pro 4.8 (both Linux and Windows) - Fixed asklong(), askseg() and askaddr()
- Dropped support for IDA Pro 4.6 and 4.6SP1 versions - Automatically generated cross reference documentation (epydoc)
- Wrapped the list chooser (see examples/choose.py) - User-specific init file support (see README,txt)
- A dozen or so IDC functions added - Deprecated some functions that have direct Python equivalents (see idc.py)
- Lots of char * API calls wrapped - Fixed exception in ScriptBox when invoked empty.
- Added Python error handling in the plugin C layer - Lots of cleanups and small fixes
- Bunch of misc small cleanups and fixes
- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt
Changes from version 0.6.0 to 0.7.0
- API CHANGE: {Next|Prev}Function() return BADADDR instead of -1 -----------------------------------
- Batch execution support (use the option -OIDAPython:yourscript.py)
- Added ScriptBox - lists previously run scripts (Hotkey:Alt-7)
Changes from version 0.5.0 to 0.6.0 - Added support for IDA Pro 4.8 (both Linux and Windows)
----------------------------------- - Dropped support for IDA Pro 4.6 and 4.6SP1 versions
- Added support for IDA Pro 4.7 (both Linux and Windows) - Wrapped the list chooser (see examples/choose.py)
- Dropped support for IDA Pro 4.6SP1 beta on Linux - A dozen or so IDC functions added
- Lots of IDC wrapper additions and fixes: - Lots of char * API calls wrapped
- Added 30+ new wrappers to idc.py - Added Python error handling in the plugin C layer
- Most Find*, Ask* and Seg* are now wrapped - Bunch of misc small cleanups and fixes
- Fixed broken NextAddr(), PrevAddr(), MakeFunction() and MakeName() - For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt
- Fixes to the makefile
- Cleanups for the idaapi wrapper - API CHANGE: {Next|Prev}Function() return BADADDR instead of -1
- Bunch of misc small cleanups and fixes
- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt
Changes from version 0.5.0 to 0.6.0
-----------------------------------
- Added support for IDA Pro 4.7 (both Linux and Windows)
- Dropped support for IDA Pro 4.6SP1 beta on Linux
- Lots of IDC wrapper additions and fixes:
- Added 30+ new wrappers to idc.py
- Most Find*, Ask* and Seg* are now wrapped
- Fixed broken NextAddr(), PrevAddr(), MakeFunction() and MakeName()
- Fixes to the makefile
- Cleanups for the idaapi wrapper
- Bunch of misc small cleanups and fixes
- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt

View File

@ -1,27 +1,27 @@
Copyright (c) 2004-2010 Gergely Erdelyi <gergely.erdelyi@d-dome.net>. All rights reserved. Copyright (c) 2004-2010 Gergely Erdelyi <gergely.erdelyi@d-dome.net>. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this 1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer. list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, 2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products 3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission. derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
OF SUCH DAMAGE. OF SUCH DAMAGE.

View File

@ -1,86 +1,86 @@
---------------------------------------------------------- ----------------------------------------------------------
IDAPython - Python plugin for Interactive Disassembler Pro IDAPython - Python plugin for Interactive Disassembler Pro
---------------------------------------------------------- ----------------------------------------------------------
WHAT IS IDAPTYHON? WHAT IS IDAPTYHON?
------------------ ------------------
IDAPython is an IDA plugin which makes it possible to write scripts IDAPython is an IDA plugin which makes it possible to write scripts
for IDA in the Python programming language. IDAPython provides full for IDA in the Python programming language. IDAPython provides full
access to both the IDA API and any installed Python module. access to both the IDA API and any installed Python module.
Check the scripts in the examples directory to get an quick glimpse. Check the scripts in the examples directory to get an quick glimpse.
AVAILABILITY AVAILABILITY
------------ ------------
Latest stable versions of IDAPython are available from Latest stable versions of IDAPython are available from
http://www.d-dome.net/idapython/ http://www.d-dome.net/idapython/
Development builds are available from Development builds are available from
http://code.google.com/p/idapython/ http://code.google.com/p/idapython/
RESOURCES RESOURCES
--------- ---------
The full function cross-reference is readable online at The full function cross-reference is readable online at
http://www.d-dome.net/idapython/reference/ http://www.d-dome.net/idapython/reference/
Bugs and enhancement requests should be submitted to Bugs and enhancement requests should be submitted to
http://code.google.com/p/idapython/issues/list http://code.google.com/p/idapython/issues/list
Mailing list for the project is hosted by Google Groups at Mailing list for the project is hosted by Google Groups at
http://groups.google.com/group/idapython http://groups.google.com/group/idapython
INSTALLATION FROM BINARIES INSTALLATION FROM BINARIES
-------------------------- --------------------------
1, Install Python 2.5 or 2.6 from http://www.python.org/ 1, Install Python 2.5 or 2.6 from http://www.python.org/
2, Copy the python and python64 directories to the IDA install directory 2, Copy the python and python64 directories to the IDA install directory
3. Copy the plugins to the %IDADIR%\plugins\ 3. Copy the plugins to the %IDADIR%\plugins\
USAGE USAGE
----- -----
The plugin has three hotkeys: The plugin has three hotkeys:
- Run script (Alt-9) - Run script (Alt-9)
- Execute Python statement(s) (Alt-8) - Execute Python statement(s) (Alt-8)
- Run previously executed script again (Alt-7) - Run previously executed script again (Alt-7)
Batch mode execution: Batch mode execution:
Start IDA with the following command line options: Start IDA with the following command line options:
-A -OIDAPython:yourscript.py file_to_work_on -A -OIDAPython:yourscript.py file_to_work_on
If you want fully unattended execution mode, make sure your script If you want fully unattended execution mode, make sure your script
exits with a qexit() call. exits with a qexit() call.
By default scripts run after the database is opened. Extended option By default scripts run after the database is opened. Extended option
format is: format is:
-OIDAPython:[N;]script.py -OIDAPython:[N;]script.py
Where N can be: Where N can be:
0: run script after opening database (default) 0: run script after opening database (default)
1: run script when UI is ready 1: run script when UI is ready
2: run script immediately on plugin load (shortly after IDA starts and before processor modules and loaders) 2: run script immediately on plugin load (shortly after IDA starts and before processor modules and loaders)
User init file: User init file:
You can place your custom settings to a file called 'idapythonrc.py' You can place your custom settings to a file called 'idapythonrc.py'
that should be placed to that should be placed to
${HOME}/.idapro/ ${HOME}/.idapro/
or or
%AppData%\Hex-Rays\IDA Pro %AppData%\Hex-Rays\IDA Pro
The user init file is read and executed at the end of the init process. The user init file is read and executed at the end of the init process.

View File

@ -1,66 +1,66 @@
Status of the IDC layer Status of the IDC layer
----------------------- -----------------------
The IDC emulation layer is complete and at par with IDA 5.1, The IDC emulation layer is complete and at par with IDA 5.1,
although it would benefit from more testing. although it would benefit from more testing.
Status of IDA API wrappers Status of IDA API wrappers
-------------------------- --------------------------
COMPLETE: all possible functions wrapped, no SWIG ifdefs COMPLETE: all possible functions wrapped, no SWIG ifdefs
INCOMPLETE: some wrapping or SWIG ifdefs still left INCOMPLETE: some wrapping or SWIG ifdefs still left
EXCLUDED: will not be wrapped EXCLUDED: will not be wrapped
allins.hpp - COMPLETE allins.hpp - COMPLETE
area.hpp - COMPLETE (necessary SWIGdefs) area.hpp - COMPLETE (necessary SWIGdefs)
auto.hpp - COMPLETE auto.hpp - COMPLETE
bytes.hpp - COMPLETE (some minor unwrapped) bytes.hpp - COMPLETE (some minor unwrapped)
compress.hpp - EXCLUDED compress.hpp - EXCLUDED
dbg.hpp - INCOMPLETE (SWIGs and lot of fixing to do) dbg.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
demangle.hpp - EXCLUDED demangle.hpp - EXCLUDED
diskio.hpp - INCOMPLETE (no SWIGs, some unwrapped) diskio.hpp - INCOMPLETE (no SWIGs, some unwrapped)
entry.hpp - COMPLETE entry.hpp - COMPLETE
enum.hpp - COMPLETE enum.hpp - COMPLETE
err.h - EXCLUDED err.h - EXCLUDED
exehdr.h - EXCLUDED exehdr.h - EXCLUDED
expr.hpp - COMPLETE (necessary SWIGs) expr.hpp - COMPLETE (necessary SWIGs)
fixup.hpp - COMPLETE fixup.hpp - COMPLETE
fpro.h - EXCLUDED fpro.h - EXCLUDED
frame.hpp - COMPLETE frame.hpp - COMPLETE
funcs.hpp - COMPLETE (necessary SWIGs, minor FIXME) funcs.hpp - COMPLETE (necessary SWIGs, minor FIXME)
gdl.hpp - EXCLUDED gdl.hpp - EXCLUDED
graph.hpp - INCOMPLETE graph.hpp - INCOMPLETE
help.h - EXCLUDED help.h - EXCLUDED
ida.hpp - COMPLETE ida.hpp - COMPLETE
idd.hpp - COMPLETE (necessary SWIGs) idd.hpp - COMPLETE (necessary SWIGs)
idp.hpp - COMPLETE idp.hpp - COMPLETE
ieee.h - EXCLUDED ieee.h - EXCLUDED
intel.hpp - EXCLUDED intel.hpp - EXCLUDED
ints.hpp - COMPLETE ints.hpp - COMPLETE
kernwin.hpp - INCOMPLETE (SWIGs and lot of fixing to do) kernwin.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
lex.hpp - EXCLUDED lex.hpp - EXCLUDED
lines.hpp - INCOMPLETE (few FIXMEs) lines.hpp - INCOMPLETE (few FIXMEs)
llong.hpp - EXCLUDED llong.hpp - EXCLUDED
loader.hpp - INCOMPLETE (few FIXMEs) loader.hpp - INCOMPLETE (few FIXMEs)
md5.h - EXCLUDED md5.h - EXCLUDED
moves.hpp - COMPLETE (some needed SWIGs) moves.hpp - COMPLETE (some needed SWIGs)
nalt.hpp - INCOMPLETE (SWIGs and lot of fixing to do) nalt.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
name.hpp - INCOMPLETE (few FIXMEs) name.hpp - INCOMPLETE (few FIXMEs)
netnode.hpp - COMPLETE netnode.hpp - COMPLETE
offset.hpp - COMPLETE offset.hpp - COMPLETE
prodir.h - EXCLUDED prodir.h - EXCLUDED
pro.h - COMPLETE (some needed SWIGs) pro.h - COMPLETE (some needed SWIGs)
queue.hpp - INCOMPLETE (one FIXME) queue.hpp - INCOMPLETE (one FIXME)
regex.h - EXCLUDED regex.h - EXCLUDED
search.hpp - COMPLETE search.hpp - COMPLETE
segment.hpp - COMPLETE segment.hpp - COMPLETE
sistack.hpp - EXCLUDED sistack.hpp - EXCLUDED
srarea.hpp - INCOMPLETE (not wrapped at all) srarea.hpp - INCOMPLETE (not wrapped at all)
strlist.hpp - COMPLETE strlist.hpp - COMPLETE
struct.hpp - COMPLETE struct.hpp - COMPLETE
typeinf.hpp - INCOMPLETE (no SWIGs, lot of fixing to do) typeinf.hpp - INCOMPLETE (no SWIGs, lot of fixing to do)
ua.hpp - INCOMPLETE (SWIGs and lot of fixing to do) ua.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
va.hpp - EXCLUDED va.hpp - EXCLUDED
vm.hpp - EXCLUDED vm.hpp - EXCLUDED
xref.hpp - COMPLETE xref.hpp - COMPLETE

View File

@ -17,12 +17,15 @@ import shutil
import sys import sys
import types import types
import zipfile import zipfile
import glob
from distutils import sysconfig from distutils import sysconfig
# Start of user configurable options # Start of user configurable options
VERBOSE = True VERBOSE = True
IDA_MAJOR_VERSION = 5 IDA_MAJOR_VERSION = 5
IDA_MINOR_VERSION = 6 IDA_MINOR_VERSION = 7
if 'IDA' in os.environ: if 'IDA' in os.environ:
IDA_SDK = os.environ['IDA'] IDA_SDK = os.environ['IDA']
else: else:
@ -32,8 +35,8 @@ else:
# IDAPython version # IDAPython version
VERSION_MAJOR = 1 VERSION_MAJOR = 1
VERSION_MINOR = 3 VERSION_MINOR = 4
VERSION_PATCH = 2 VERSION_PATCH = 0
# Determine Python version # Determine Python version
PYTHON_MAJOR_VERSION = int(platform.python_version()[0]) PYTHON_MAJOR_VERSION = int(platform.python_version()[0])
@ -43,7 +46,7 @@ PYTHON_MINOR_VERSION = int(platform.python_version()[2])
PYTHON_INCLUDE_DIRECTORY = sysconfig.get_config_var('INCLUDEPY') PYTHON_INCLUDE_DIRECTORY = sysconfig.get_config_var('INCLUDEPY')
# Swig command-line parameters # Swig command-line parameters
SWIG_OPTIONS = '-modern -python -c++ -w451 -shadow -D__GNUC__' SWIG_OPTIONS = '-modern -python -c++ -w451 -shadow -D__GNUC__ -DNO_OBSOLETE_FUNCS'
# Common macros for all compilations # Common macros for all compilations
COMMON_MACROS = [ COMMON_MACROS = [
@ -75,6 +78,7 @@ BINDIST_MANIFEST = [
"examples/structure.py", "examples/structure.py",
"examples/ex_gdl_qflow_chart.py", "examples/ex_gdl_qflow_chart.py",
"examples/ex_strings.py", "examples/ex_strings.py",
"examples/ex_add_menu_item.py",
"examples/ex_func_chooser.py", "examples/ex_func_chooser.py",
"examples/ex_choose2.py", "examples/ex_choose2.py",
"examples/ex_debug_names.py", "examples/ex_debug_names.py",
@ -162,7 +166,8 @@ class BuilderBase:
includestring, includestring,
macrostring) macrostring)
if VERBOSE: print cmdstring if VERBOSE:
print cmdstring
return os.system(cmdstring) return os.system(cmdstring)
def link(self, objects, outfile, libpaths=[], libraries=[], extra_parameters=None): def link(self, objects, outfile, libpaths=[], libraries=[], extra_parameters=None):
@ -413,7 +418,73 @@ def build_source_package():
srcmanifest.extend([(x, "python") for x in "python/init.py", "python/idc.py", "python/idautils.py"]) srcmanifest.extend([(x, "python") for x in "python/init.py", "python/idc.py", "python/idautils.py"])
build_distribution(srcmanifest, SRCDISTDIR, ea64=False, nukeold=True) build_distribution(srcmanifest, SRCDISTDIR, ea64=False, nukeold=True)
def gen_docs(z = False):
print "Generating documentation....."
old_dir = os.getcwd()
try:
curdir = os.getcwd() + os.sep
docdir = 'idapython-reference-%d.%d.%d' % (VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH)
sys.path.append(curdir + 'python')
sys.path.append(curdir + 'tools')
sys.path.append(curdir + 'docs')
import epydoc.cli
import swigdocs
os.chdir('docs')
PYWRAPS_FN = 'pywraps'
swigdocs.gen_docs(outfn = PYWRAPS_FN + '.py')
epydoc.cli.optparse.sys.argv = [ 'epydoc',
'--no-sourcecode',
'-u', 'http://code.google.com/p/idapython/',
'--navlink', '<a href="http://www.hex-rays.com/idapro/idapython_docs/">IDAPython Reference</a>',
'--no-private',
'--simple-term',
'-o', docdir,
'--html',
'idc', 'idautils', PYWRAPS_FN, 'idaapi']
# Generate the documentation
epydoc.cli.cli()
print "Documentation generated!"
# Clean temp files
for f in [PYWRAPS_FN + '.py', PYWRAPS_FN + '.pyc']:
if os.path.exists(f):
os.unlink(f)
if z:
z = docdir + '-doc.zip'
zip = zipfile.ZipFile(z, "w", zipfile.ZIP_DEFLATED)
for fn in glob.glob(docdir + os.sep + '*'):
zip.write(fn)
zip.close()
print "Documentation compressed to", z
except Exception, e:
print 'Failed to generate documentation:', e
finally:
os.chdir(old_dir)
return
def usage():
print """IDAPython build script.
Available switches:
--doc:
Generate documentation into the 'docs' directory
--zip:
Used with '--doc' switch. It will compress the generated documentation
--ea64:
Builds also the 64bit version of the plugin
--no-early-load:
The plugin will be compiled as normal plugin
This switch disables processor, plugin and loader scripts
"""
def main(): def main():
if '--help' in sys.argv:
return usage()
elif '--doc' in sys.argv:
return gen_docs(z = '--zip' in sys.argv)
# Do 64-bit build? # Do 64-bit build?
ea64 = '--ea64' in sys.argv ea64 = '--ea64' in sys.argv
build_binary_package(ea64=False, nukeold=True) build_binary_package(ea64=False, nukeold=True)
@ -422,4 +493,4 @@ def main():
build_source_package() build_source_package()
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -0,0 +1,18 @@
import idaapi
def cb(*args):
print "Callback called!"
return 1
try:
if ctx:
idaapi.del_menu_item(ctx)
except:
pass
ctx = idaapi.add_menu_item("Search/", "X", "", 0, cb, tuple("hello world"))
if ctx is None:
print "Failed to add menu!"
del ctx
else:
print "Menu added successfully!"

View File

@ -15,7 +15,7 @@ class mycv_t(simplecustviewer_t):
if sn: if sn:
title += " %d" % sn title += " %d" % sn
# Create the customview # Create the customviewer
if not simplecustviewer_t.Create(self, title): if not simplecustviewer_t.Create(self, title):
return False return False
self.menu_hello = self.AddPopupMenu("Hello") self.menu_hello = self.AddPopupMenu("Hello")
@ -24,6 +24,8 @@ class mycv_t(simplecustviewer_t):
for i in xrange(0, 100): for i in xrange(0, 100):
self.AddLine("Line %d" % i) self.AddLine("Line %d" % i)
# self.Jump(0)
return True return True
def OnClick(self, shift): def OnClick(self, shift):
@ -71,6 +73,7 @@ class mycv_t(simplecustviewer_t):
# ESCAPE? # ESCAPE?
if vkey == 27: if vkey == 27:
self.Close() self.Close()
# VK_DELETE
elif vkey == 46: elif vkey == 46:
n = self.GetLineNo() n = self.GetLineNo()
if n is not None: if n is not None:
@ -129,10 +132,10 @@ class mycv_t(simplecustviewer_t):
Hint requested for the given line number. Hint requested for the given line number.
@param lineno: The line number (zero based) @param lineno: The line number (zero based)
@return: @return:
- string: a string containing the hint - tuple(number of important lines, hint string)
- None: if no hint available - None: if no hint available
""" """
return "OnHint, line=%d" % lineno return (1, "OnHint, line=%d" % lineno)
def OnPopupMenu(self, menu_id): def OnPopupMenu(self, menu_id):
""" """

2435
python.cpp

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,228 +1,79 @@
#!/usr/bin/env python #!/usr/bin/env python
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# IDAPython - Python plugin for Interactive Disassembler Pro # IDAPython - Python plugin for Interactive Disassembler Pro
# #
# Copyright (c) 2004-2010 Gergely Erdelyi <gergely.erdelyi@d-dome.net> # Copyright (c) 2004-2010 Gergely Erdelyi <gergely.erdelyi@d-dome.net>
# #
# All rights reserved. # All rights reserved.
# #
# For detailed copyright information see the file COPYING in # For detailed copyright information see the file COPYING in
# the root of the distribution archive. # the root of the distribution archive.
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# init.py - Essential init routines # init.py - Essential init routines
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
import os import os
import sys import sys
import time import time
import warnings import warnings
import _idaapi
import _idaapi
# __EA64__ is set if IDA is running in 64-bit mode
# __EA64__ is set if IDA is running in 64-bit mode __EA64__ = _idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL
__EA64__ = _idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL
# -----------------------------------------------------------------------
# ----------------------------------------------------------------------- # Take over the standard text outputs
def addscriptpath(script): # -----------------------------------------------------------------------
""" class IDAPythonStdOut:
Add the path part of the scriptfile to the system path to """
allow modules to be loaded from the same place. Dummy file-like class that receives stout and stderr
"""
Each path is added only once. def write(self, text):
""" # Swap out the unprintable characters
pathfound = 0 text = text.decode('ascii', 'replace').encode('ascii', 'replace')
# Print to IDA message window
scriptpath = os.path.dirname(script) _idaapi.msg(text.replace("%", "%%"))
for pathitem in sys.path: def flush(self):
if pathitem == scriptpath: pass
pathfound = 1
break def isatty(self):
return False
if pathfound == 0:
sys.path.append(scriptpath) # -----------------------------------------------------------------------
def print_banner():
# Add the script to ScriptBox if it's not there yet banner = [
if not script in scriptbox.list: "Python interpreter version %d.%d.%d %s (serial %d)" % sys.version_info,
scriptbox.list.insert(0, script) "Copyright (c) 1990-2010 Python Software Foundation - http://www.python.org/",
"",
# ------------------------------------------------------------ "IDAPython" + (" 64-bit" if __EA64__ else "") + " version %d.%d.%d %s (serial %d)" % IDAPYTHON_VERSION,
def runscript(script): "Copyright (c) 2004-2010 Gergely Erdelyi - http://code.google.com/p/idapython/"
""" ]
Run the specified script after adding its directory path to sepline = '-' * max([len(s) for s in banner])
system path.
print sepline
This function is used by the low-level plugin code. print "\n".join(banner)
""" print sepline
addscriptpath(script)
watchdog.reset() # -----------------------------------------------------------------------
# Save the argv, path, I/O and base modules for later cleanup
argv = sys.argv # Redirect stderr and stdout to the IDA message window
path = sys.path sys.stdout = sys.stderr = IDAPythonStdOut()
stdio = [sys.stdin, sys.stdout, sys.stderr]
basemodules = sys.modules.copy() # Assign a default sys.argv
sys.argv = [ script ] sys.argv = [""]
# Adjust the __file__ path in the globals we pass to the script
g = globals() # Have to make sure Python finds our modules
old__file__ = g['__file__'] if '__file__' in g else '' sys.path.append(_idaapi.idadir("python"))
g['__file__'] = script
try: # Import all the required modules
execfile(script, g) from idaapi import Choose, get_user_idadir, cvar, Choose2, Appcall
except: from idc import *
raise from idautils import *
finally: import idaapi
# Restore the globals to the state before the script was run
g['__file__'] = old__file__ # Load the users personal init file
sys.argv = argv userrc = get_user_idadir() + os.sep + "idapythonrc.py"
sys.path = path if os.path.exists(userrc):
sys.stdin, sys.stdout, sys.stderr = stdio idaapi.IDAPython_ExecScript(userrc, globals())
# Clean up the modules loaded by the script
for module in sys.modules.keys(): # All done, ready to rock.
if not module in basemodules:
del(sys.modules[module])
# -----------------------------------------------------------------------
def print_banner():
banner = [
"Python interpreter version %d.%d.%d %s (serial %d)" % sys.version_info,
"Copyright (c) 1990-2010 Python Software Foundation - http://www.python.org/",
"",
"IDAPython" + (" 64-bit" if __EA64__ else "") + " version %d.%d.%d %s (serial %d)" % IDAPYTHON_VERSION,
"Copyright (c) 2004-2010 Gergely Erdelyi - http://code.google.com/p/idapython/"
]
sepline = '-' * max([len(s) for s in banner])
print sepline
print "\n".join(banner)
print sepline
# -----------------------------------------------------------------------
# Take over the standard text outputs
# -----------------------------------------------------------------------
class MyStdOut:
"""
Dummy file-like class that receives stout and stderr
"""
def write(self, text):
# Swap out the unprintable characters
text = text.decode('ascii', 'replace').encode('ascii', 'replace')
# Print to IDA message window
_idaapi.msg(text.replace("%", "%%"))
def flush(self):
pass
def isatty(self):
return False
# Redirect stderr and stdout to the IDA message window
sys.stdout = sys.stderr = MyStdOut()
# Assign a default sys.argv
sys.argv = [""]
# Have to make sure Python finds our modules
sys.path.append(_idaapi.idadir("python"))
# -----------------------------------------------------------------------
# Import all the required modules
# -----------------------------------------------------------------------
from idaapi import Choose, get_user_idadir, cvar, Choose2, Appcall
from idc import *
from idautils import *
import idaapi
# -----------------------------------------------------------------------
# Build up the ScriptBox tool
# -----------------------------------------------------------------------
class ScriptBox(Choose):
def __init__(self, list=None):
if list:
self.list = list
else:
self.list = []
Choose.__init__(self, self.list, "ScriptBox", 1)
self.width = 50
def run(self):
if len(self.list) == 0:
Warning("ScriptBox history is empty.\nRun some script with Alt-9 and try again.")
return None
n = self.choose()
if n > 0:
runscript(self.list[n-1])
def addscript(self, scriptpath):
self.list.append(scriptpath)
scriptbox = ScriptBox()
# -----------------------------------------------------------------------
# Watchdog to catch runaway scripts after a specified timeout
#
# Usage:
# watchdog.install()
# watchdog.activate(10) # Use 10-second timeout
#
# Note: The watchdog only works for code running inside
# functions, not in global/module namespace.
# -----------------------------------------------------------------------
class WatchDog():
"""
Python tracer-based watchdog class
"""
def __init__(self, timeout=10):
self.timestamp = 0
self.timeout = timeout
self.installed = False
self.active = False
def install(self):
""" Install the tracer function, required for the watchdog """
if not self.installed:
sys.settrace(self.tracer)
self.installed = True
def activate(self, timeout=None):
""" Activate the watchdog, with optional timeout change """
assert self.installed, "WatchDog must be installed before activating"
if timeout:
self.timeout = timeout
self.reset()
self.active = True
def deactivate(self):
""" Deactivate the watchdog """
self.active = True
def reset(self):
""" Reset the timer, useful for long-running scripts """
self.timestamp = time.clock()
def tracer(self, frame, event, arg):
""" Tracer function that receives the tracing events """
if not self.active:
return None
if event == 'line':
if time.clock() - self.timestamp > self.timeout:
if AskYN(0, "The script has not finished in %d seconds\nWould you like to stop it now?" % self.timeout) == 1:
raise KeyboardInterrupt
else:
self.timestamp = time.clock()
return self.tracer
watchdog = WatchDog(10)
# -----------------------------------------------------------------------
# Load the users personal init file
userrc = get_user_idadir() + os.sep + "idapythonrc.py"
# -----------------------------------------------------------------------
if os.path.exists(userrc):
runscript(userrc)
# Remove the user script from the history
del scriptbox.list[0]
# All done, ready to rock.

View File

@ -7,17 +7,25 @@
#define PYUL_DEFINED #define PYUL_DEFINED
#ifdef __EA64__ #ifdef __EA64__
typedef unsigned PY_LONG_LONG pyul_t; typedef unsigned PY_LONG_LONG pyul_t;
typedef PY_LONG_LONG pyl_t;
#else #else
typedef unsigned long pyul_t; typedef unsigned long pyul_t;
typedef long pyl_t;
#endif #endif
#endif #endif
#ifdef __EA64__ #ifdef __EA64__
#define PY_FMT64 "K" #define PY_FMT64 "K"
#define PY_SFMT64 "L"
#else #else
#define PY_FMT64 "k" #define PY_FMT64 "k"
#define PY_SFMT64 "l"
#endif #endif
#define S_IDAAPI_MODNAME "idaapi"
#define S_IDC_MODNAME "idc"
#define S_IDAAPI_EXECSCRIPT "IDAPython_ExecScript"
// Vector of PyObject* // Vector of PyObject*
typedef qvector<PyObject *> ppyobject_vec_t; typedef qvector<PyObject *> ppyobject_vec_t;
@ -27,6 +35,19 @@ typedef qvector<PyObject *> ppyobject_vec_t;
#define PY_ICID_BYREF 1 #define PY_ICID_BYREF 1
#define PY_ICID_OPAQUE 2 #define PY_ICID_OPAQUE 2
//------------------------------------------------------------------------
// Constants used with the notify_when()
#define NW_OPENIDB 0x0001
#define NW_OPENIDB_SLOT 0
#define NW_CLOSEIDB 0x0002
#define NW_CLOSEIDB_SLOT 1
#define NW_INITIDA 0x0004
#define NW_INITIDA_SLOT 2
#define NW_TERMIDA 0x0008
#define NW_TERMIDA_SLOT 3
#define NW_REMOVE 0x0010 // Uninstall flag
#define NW_EVENTSCNT 4 // Count of notify_when codes
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Constants used by the pyvar_to_idcvar and idcvar_to_pyvar functions // Constants used by the pyvar_to_idcvar and idcvar_to_pyvar functions
#define CIP_FAILED -1 // Conversion error #define CIP_FAILED -1 // Conversion error
@ -36,47 +57,72 @@ typedef qvector<PyObject *> ppyobject_vec_t;
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// All the exported functions from PyWraps are forward declared here // All the exported functions from PyWraps are forward declared here
insn_t *insn_t_get_clink(PyObject *self);
op_t *op_t_get_clink(PyObject *self);
// Tries to import a module and swallows the exception if it fails and returns NULL // Tries to import a module and swallows the exception if it fails and returns NULL
PyObject *PyImport_TryImportModule(const char *name); PyObject *PyImport_TryImportModule(const char *name);
// Tries to get an attribute and swallows the exception if it fails and returns NULL // Tries to get an attribute and swallows the exception if it fails and returns NULL
PyObject *PyObject_TryGetAttrString(PyObject *py_var, const char *attr); PyObject *PyObject_TryGetAttrString(PyObject *py_var, const char *attr);
// Converts a Python number (LONGLONG or normal integer) to an IDC variable (VT_LONG or VT_INT64) // Converts a Python number (LONGLONG or normal integer) to an IDC variable (VT_LONG or VT_INT64)
bool PyGetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var); bool PyGetNumberAsIDC(PyObject *py_var, idc_value_t *idc_var);
// Converts a Python number to an uint64 and indicates whether the number was a long number // Converts a Python number to an uint64 and indicates whether the number was a long number
bool PyGetNumber(PyObject *py_var, uint64 *num, bool *is_64 = NULL); bool PyGetNumber(PyObject *py_var, uint64 *num, bool *is_64 = NULL);
// Checks if an Python object can be treated like a sequence // Checks if an Python object can be treated like a sequence
bool PyIsSequenceType(PyObject *obj); bool PyIsSequenceType(PyObject *obj);
// Returns an error string from the last exception (and clears it) // Returns an error string from the last exception (and clears it)
bool PyGetError(qstring *out = NULL); bool PyGetError(qstring *out = NULL);
// If an error occured (it calls PyGetError) it displays it and return TRUE // If an error occured (it calls PyGetError) it displays it and return TRUE
bool PyShowErr(const char *cb_name); bool PyShowErr(const char *cb_name);
// [De]Initializes PyWraps // Utility function to create a class instance whose constructor takes zero arguments
bool init_pywraps(); PyObject *create_idaapi_class_instance0(const char *clsname);
void deinit_pywraps();
// Utility function to create linked class instances
// Returns the string representation of a PyObject PyObject *create_idaapi_linked_class_instance(const char *clsname, void *lnk);
bool PyObjectToString(PyObject *obj, qstring *out);
// [De]Initializes PyWraps
// Converts Python variable to IDC variable bool init_pywraps();
// gvar_sn is used in case the Python object was a created from a call to idcvar_to_pyvar and the IDC object was a VT_REF void deinit_pywraps();
int pyvar_to_idcvar(
PyObject *py_var, // Returns the string representation of a PyObject
idc_value_t *idc_var, bool PyObjectToString(PyObject *obj, qstring *out);
int *gvar_sn = NULL);
// Utility function to convert a python object to an IDC object
// Converts from IDC to Python // and sets a python exception on failure.
// We support converting VT_REF IDC variable types bool convert_pyobj_to_idc_exc(PyObject *py_obj, idc_value_t *idc_obj);
int idcvar_to_pyvar(
const idc_value_t &idc_var, // Converts Python variable to IDC variable
// gvar_sn is used in case the Python object was a created from a call to idcvar_to_pyvar and the IDC object was a VT_REF
int pyvar_to_idcvar(
PyObject *py_var,
idc_value_t *idc_var,
int *gvar_sn = NULL);
// Converts from IDC to Python
// We support converting VT_REF IDC variable types
int idcvar_to_pyvar(
const idc_value_t &idc_var,
PyObject **py_var); PyObject **py_var);
// Walks a Python list or Sequence and calls the callback
Py_ssize_t pyvar_walk_list(
PyObject *py_list,
int (idaapi *cb)(PyObject *py_item, Py_ssize_t index, void *ud) = NULL,
void *ud = NULL);
// Returns a reference to a class
PyObject *get_idaapi_attr(const char *attr);
// notify_when()
bool pywraps_nw_term();
bool pywraps_nw_notify(int slot, ...);
bool pywraps_nw_init();
#endif #endif

View File

@ -61,9 +61,17 @@
%ignore term_flags; %ignore term_flags;
%ignore reset_flags; %ignore reset_flags;
%ignore flush_flags; %ignore flush_flags;
%ignore data_type_t;
// TODO: These could be fixed if someone needs them. %ignore data_format_t;
%ignore get_custom_data_type;
%ignore get_custom_data_format;
%ignore unregister_custom_data_format;
%ignore register_custom_data_format;
%ignore unregister_custom_data_type;
%ignore register_custom_data_type;
%ignore get_many_bytes; %ignore get_many_bytes;
// TODO: This could be fixed (if needed)
%ignore set_dbgmem_source; %ignore set_dbgmem_source;
%include "bytes.hpp" %include "bytes.hpp"
@ -76,6 +84,12 @@
%rename (nextthat) py_nextthat; %rename (nextthat) py_nextthat;
%rename (prevthat) py_prevthat; %rename (prevthat) py_prevthat;
%rename (get_custom_data_type) py_get_custom_data_type;
%rename (get_custom_data_format) py_get_custom_data_format;
%rename (unregister_custom_data_format) py_unregister_custom_data_format;
%rename (register_custom_data_format) py_register_custom_data_format;
%rename (unregister_custom_data_type) py_unregister_custom_data_type;
%rename (register_custom_data_type) py_register_custom_data_type;
%rename (get_many_bytes) py_get_many_bytes; %rename (get_many_bytes) py_get_many_bytes;
%{ %{
@ -95,10 +109,505 @@ static bool idaapi py_testf_cb(flags_t flags, void *ud)
// Wraps the (next|prev)that() // Wraps the (next|prev)that()
static ea_t py_npthat(ea_t ea, ea_t bound, PyObject *py_callable, bool next) static ea_t py_npthat(ea_t ea, ea_t bound, PyObject *py_callable, bool next)
{ {
if (!PyCallable_Check(py_callable)) if ( !PyCallable_Check(py_callable) )
return BADADDR; return BADADDR;
return (next ? nextthat : prevthat)(ea, bound, py_testf_cb, py_callable); return (next ? nextthat : prevthat)(ea, bound, py_testf_cb, py_callable);
} }
//------------------------------------------------------------------------
class py_custom_data_type_t
{
data_type_t dt;
qstring name, menu_name, hotkey, asm_keyword;
int dtid; // The data format id
PyObject *py_self; // Associated Python object
// may create data? NULL means always may
static bool idaapi s_may_create_at(
void *ud, // user-defined data
ea_t ea, // address of the future item
size_t nbytes) // size of the future item
{
py_custom_data_type_t *_this = (py_custom_data_type_t *)ud;
PyObject *py_result = PyObject_CallMethod(_this->py_self, (char *)S_MAY_CREATE_AT, PY_FMT64 PY_FMT64, pyul_t(ea), pyul_t(nbytes));
PyShowErr(S_MAY_CREATE_AT);
bool ok = py_result != NULL && PyObject_IsTrue(py_result);
Py_XDECREF(py_result);
return ok;
}
// !=NULL means variable size datatype
static asize_t idaapi s_calc_item_size(
// This function is used to determine
// size of the (possible) item at 'ea'
void *ud, // user-defined data
ea_t ea, // address of the item
asize_t maxsize) // maximal size of the item
{
// Returns: 0-no such item can be created/displayed
// this callback is required only for varsize datatypes
py_custom_data_type_t *_this = (py_custom_data_type_t *)ud;
PyObject *py_result = PyObject_CallMethod(_this->py_self, (char *)S_CALC_ITEM_SIZE, PY_FMT64 PY_FMT64, pyul_t(ea), pyul_t(maxsize));
if ( PyShowErr(S_CALC_ITEM_SIZE) || py_result == NULL )
return 0;
uint64 num = 0;
PyGetNumber(py_result, &num);
Py_XDECREF(py_result);
return asize_t(num);
}
public:
const char *get_name() const { return name.c_str(); }
py_custom_data_type_t()
{
dtid = -1;
py_self = NULL;
}
int register_dt(PyObject *py_obj)
{
// Already registered?
if ( dtid >= 0 )
return dtid;
memset(&dt, 0, sizeof(dt));
dt.cbsize = sizeof(dt);
dt.ud = this;
PyObject *py_attr = NULL;
do
{
// name
py_attr = PyObject_TryGetAttrString(py_obj, S_NAME);
if ( py_attr == NULL || !PyString_Check(py_attr) )
break;
name = PyString_AsString(py_attr);
dt.name = name.c_str();
Py_DECREF(py_attr);
// value_size
py_attr = PyObject_TryGetAttrString(py_obj, S_VALUE_SIZE);
if ( py_attr != NULL )
dt.value_size = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
// props
py_attr = PyObject_TryGetAttrString(py_obj, S_PROPS);
if ( py_attr != NULL )
dt.props = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
// menu_name
py_attr = PyObject_TryGetAttrString(py_obj, S_MENU_NAME);
if ( py_attr != NULL && PyString_Check(py_attr) )
{
menu_name = PyString_AsString(py_attr);
dt.menu_name = menu_name.c_str();
}
Py_XDECREF(py_attr);
// asm_keyword
py_attr = PyObject_TryGetAttrString(py_obj, S_ASM_KEYWORD);
if ( py_attr != NULL && PyString_Check(py_attr) )
{
asm_keyword = PyString_AsString(py_attr);
dt.asm_keyword = asm_keyword.c_str();
}
Py_XDECREF(py_attr);
// hotkey
py_attr = PyObject_TryGetAttrString(py_obj, S_HOTKEY);
if ( py_attr != NULL && PyString_Check(py_attr) )
{
hotkey = PyString_AsString(py_attr);
dt.hotkey = hotkey.c_str();
}
Py_XDECREF(py_attr);
// may_create_at
py_attr = PyObject_TryGetAttrString(py_obj, S_MAY_CREATE_AT);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
dt.may_create_at = s_may_create_at;
Py_XDECREF(py_attr);
// calc_item_size
py_attr = PyObject_TryGetAttrString(py_obj, S_CALC_ITEM_SIZE);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
dt.calc_item_size = s_calc_item_size;
Py_XDECREF(py_attr);
// Clear attribute
py_attr = NULL;
// Now try to register
dtid = register_custom_data_type(&dt);
if ( dtid < 0 )
break;
// Hold reference to the PyObject
Py_INCREF(py_obj);
py_self = py_obj;
py_attr = PyInt_FromLong(dtid);
PyObject_SetAttrString(py_obj, S_ID, py_attr);
Py_DECREF(py_attr);
// Done with attribute
py_attr = NULL;
} while ( false );
Py_XDECREF(py_attr);
return dtid;
}
bool unregister_dt()
{
if ( dtid < 0 )
return true;
if ( !unregister_custom_data_type(dtid) )
return false;
// Release reference of Python object
Py_XDECREF(py_self);
py_self = NULL;
dtid = -1;
return true;
}
~py_custom_data_type_t()
{
unregister_dt();
}
};
typedef std::map<int, py_custom_data_type_t *> py_custom_data_type_map_t;
static py_custom_data_type_map_t py_dt_map;
//------------------------------------------------------------------------
class py_custom_data_format_t
{
private:
data_format_t df;
int dfid;
PyObject *py_self;
qstring name, menu_name, hotkey;
static bool idaapi s_print( // convert to colored string
void *ud, // user-defined data
qstring *out, // output buffer. may be NULL
const void *value, // value to print. may not be NULL
asize_t size, // size of value in bytes
ea_t current_ea, // current address (BADADDR if unknown)
int operand_num, // current operand number
int dtid) // custom data type id
{
// Build a string from the buffer
PyObject *py_value = PyString_FromStringAndSize((const char *)value, Py_ssize_t(size));
if ( py_value == NULL )
return false;
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_PRINTF,
"O" PY_FMT64 "ii",
py_value,
pyul_t(current_ea),
operand_num,
dtid);
// Done with the string
Py_DECREF(py_value);
// Error while calling the function?
if ( PyShowErr(S_PRINTF) || py_result == NULL )
return false;
bool ok = false;
if ( PyString_Check(py_result) )
{
Py_ssize_t len;
char *buf;
if ( out != NULL && PyString_AsStringAndSize(py_result, &buf, &len) != -1 )
{
out->qclear();
out->append(buf, len);
}
ok = true;
}
Py_DECREF(py_result);
return ok;
}
static bool idaapi s_scan( // convert from uncolored string
void *ud, // user-defined data
bytevec_t *value, // output buffer. may be NULL
const char *input, // input string. may not be NULL
ea_t current_ea, // current address (BADADDR if unknown)
int operand_num, // current operand number (-1 if unknown)
qstring *errstr) // buffer for error message
{
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
PyObject *py_result = PyObject_CallMethod(
_this->py_self,
(char *)S_SCAN,
"s" PY_FMT64,
input,
pyul_t(current_ea),
operand_num);
// Error while calling the function?
if ( PyShowErr(S_SCAN) || py_result == NULL)
return false;
bool ok = false;
do
{
// We expect a tuple(bool, string|None)
if ( !PyTuple_Check(py_result) || PyTuple_Size(py_result) != 2 )
break;
// Borrow references
PyObject *py_bool = PyTuple_GetItem(py_result, 0);
PyObject *py_val = PyTuple_GetItem(py_result, 1);
// Get return code from Python
ok = PyObject_IsTrue(py_bool);
// We expect None or the value (depending on probe)
if ( ok )
{
// Probe-only? Then okay, no need to extract the 'value'
if ( value == NULL )
break;
Py_ssize_t len;
char *buf;
if ( PyString_AsStringAndSize(py_val, &buf, &len) != -1 )
{
value->qclear();
value->append(buf, len);
}
}
// An error occured?
else
{
// Make sure the user returned (False, String)
if ( py_bool != Py_False || !PyString_Check(py_val) )
{
*errstr = "Invalid return value returned from the Python callback!";
break;
}
// Get the error message
*errstr = PyString_AsString(py_val);
}
} while ( false );
Py_DECREF(py_result);
return ok;
}
static void idaapi s_analyze( // analyze custom data format occurrence
void *ud, // user-defined data
ea_t current_ea, // current address (BADADDR if unknown)
int operand_num) // current operand number
// this callback can be used to create
// xrefs from the current item.
// this callback may be missing.
{
py_custom_data_format_t *_this = (py_custom_data_format_t *) ud;
PyObject *py_result = PyObject_CallMethod(_this->py_self, (char *)S_ANALYZE, PY_FMT64 "i", pyul_t(current_ea),operand_num);
PyShowErr(S_ANALYZE);
Py_XDECREF(py_result);
}
public:
py_custom_data_format_t()
{
dfid = -1;
py_self = NULL;
}
const char *get_name() const { return name.c_str(); }
int register_df(int dtid, PyObject *py_obj)
{
// Already registered?
if ( dfid >= 0 )
return dfid;
memset(&df, 0, sizeof(df));
df.cbsize = sizeof(df);
df.ud = this;
PyObject *py_attr = NULL;
do
{
// name
py_attr = PyObject_TryGetAttrString(py_obj, S_NAME);
if ( py_attr == NULL || !PyString_Check(py_attr) )
break;
name = PyString_AsString(py_attr);
df.name = name.c_str();
Py_DECREF(py_attr);
// menu_name
py_attr = PyObject_TryGetAttrString(py_obj, S_MENU_NAME);
if ( py_attr != NULL && PyString_Check(py_attr) )
{
menu_name = PyString_AsString(py_attr);
df.menu_name = menu_name.c_str();
}
Py_XDECREF(py_attr);
// props
py_attr = PyObject_TryGetAttrString(py_obj, S_PROPS);
if ( py_attr != NULL )
df.props = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
// hotkey
py_attr = PyObject_TryGetAttrString(py_obj, S_HOTKEY);
if ( py_attr != NULL && PyString_Check(py_attr) )
{
hotkey = PyString_AsString(py_attr);
df.hotkey = hotkey.c_str();
}
Py_XDECREF(py_attr);
// value_size
py_attr = PyObject_TryGetAttrString(py_obj, S_VALUE_SIZE);
if ( py_attr != NULL )
df.value_size = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
// text_width
py_attr = PyObject_TryGetAttrString(py_obj, S_TEXT_WIDTH);
if ( py_attr != NULL )
df.text_width = PyInt_AsLong(py_attr);
Py_XDECREF(py_attr);
// print cb
py_attr = PyObject_TryGetAttrString(py_obj, S_PRINTF);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
df.print = s_print;
Py_XDECREF(py_attr);
// scan cb
py_attr = PyObject_TryGetAttrString(py_obj, S_SCAN);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
df.scan = s_scan;
Py_XDECREF(py_attr);
// analyze cb
py_attr = PyObject_TryGetAttrString(py_obj, S_ANALYZE);
if ( py_attr != NULL && PyCallable_Check(py_attr) )
df.analyze = s_analyze;
Py_XDECREF(py_attr);
// Done with attribute
py_attr = NULL;
// Now try to register
dfid = register_custom_data_format(dtid, &df);
if ( dfid < 0 )
break;
// Hold reference to the PyObject
Py_INCREF(py_obj);
py_self = py_obj;
py_attr = PyInt_FromLong(dfid);
PyObject_SetAttrString(py_obj, S_ID, py_attr);
Py_DECREF(py_attr);
py_attr = NULL;
} while ( false );
Py_XDECREF(py_attr);
return dfid;
}
bool unregister_df(int dtid)
{
// Never registered?
if ( dfid < 0 )
return true;
if ( !unregister_custom_data_format(dtid, dfid) )
return false;
// Release reference of Python object
Py_XDECREF(py_self);
py_self = NULL;
dfid = -1;
return true;
}
~py_custom_data_format_t()
{
}
};
//------------------------------------------------------------------------
// Helper class to bind <dtid, dfid> pairs to py_custom_data_format_t
class py_custom_data_format_list_t
{
struct py_custom_data_format_entry_t
{
int dtid;
int dfid;
py_custom_data_format_t *df;
};
typedef qvector<py_custom_data_format_entry_t> ENTRY;
ENTRY entries;
public:
typedef ENTRY::iterator POS;
void add(int dtid, int dfid, py_custom_data_format_t *df)
{
py_custom_data_format_entry_t &e = entries.push_back();
e.dtid = dtid;
e.dfid = dfid;
e.df = df;
}
py_custom_data_format_t *find(int dtid, int dfid, POS *loc = NULL)
{
for ( POS it=entries.begin(), it_end = entries.end(); it!=it_end; ++it )
{
if ( it->dfid == dfid && it->dtid == dtid )
{
if ( loc != NULL )
*loc = it;
return it->df;
}
}
return NULL;
}
void erase(POS &pos)
{
entries.erase(pos);
}
};
static py_custom_data_format_list_t py_df_list;
//------------------------------------------------------------------------
static PyObject *py_data_type_to_py_dict(const data_type_t *dt)
{
return Py_BuildValue("{s:" PY_FMT64 ",s:i,s:i,s:s,s:s,s:s,s:s}",
S_VALUE_SIZE, pyul_t(dt->value_size),
S_PROPS, dt->props,
S_CBSIZE, dt->cbsize,
S_NAME, dt->name == NULL ? "" : dt->name,
S_MENU_NAME, dt->menu_name == NULL ? "" : dt->menu_name,
S_HOTKEY, dt->hotkey == NULL ? "" : dt->hotkey,
S_ASM_KEYWORD, dt->asm_keyword == NULL ? "" : dt->asm_keyword);
}
//------------------------------------------------------------------------
static PyObject *py_data_format_to_py_dict(const data_format_t *df)
{
return Py_BuildValue("{s:i,s:i,s:i,s:" PY_FMT64 ",s:s,s:s,s:s}",
S_PROPS, df->props,
S_CBSIZE, df->cbsize,
S_TEXT_WIDTH, df->text_width,
S_VALUE_SIZE, pyul_t(df->value_size),
S_NAME, df->name == NULL ? "" : df->name,
S_MENU_NAME, df->menu_name == NULL ? "" : df->menu_name,
S_HOTKEY, df->hotkey == NULL ? "" : df->hotkey);
}
//</code(py_bytes)> //</code(py_bytes)>
%} %}
@ -117,34 +626,441 @@ static ea_t py_prevthat(ea_t ea, ea_t minea, PyObject *callable)
} }
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Get the specified number of bytes of the program into the buffer. /*
static PyObject *py_get_many_bytes(ea_t ea, int size) #<pydoc>
def get_many_bytes(ea):
"""
Get the specified number of bytes of the program into the buffer.
@param ea: program address
@param size: number of bytes to return
@return: None or the string buffer
"""
pass
#</pydoc>
*/
static PyObject *py_get_many_bytes(ea_t ea, unsigned int size)
{ {
do do
{ {
if (size <= 0) if ( size <= 0 )
break; break;
// Allocate memory
char *buf = (char *) qalloc(size); // Allocate memory via Python
if (buf == NULL) PyObject *py_buf = PyString_FromStringAndSize(NULL, Py_ssize_t(size));
if ( py_buf == NULL )
break; break;
// Read bytes // Read bytes
bool ok = get_many_bytes(ea, buf, size); bool ok = get_many_bytes(ea, PyString_AsString(py_buf), size);
// If ok, create a python string // If failed, dispose the Python string
PyObject *py_buf; if ( !ok )
if (ok) {
py_buf = PyString_FromStringAndSize(buf, size); Py_DECREF(py_buf);
// Free buffer py_buf = Py_None;
qfree(buf); Py_INCREF(py_buf);
}
// Return buffer to Python
if (ok) return py_buf;
return py_buf; } while ( false );
} while (false);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
//------------------------------------------------------------------------
/*
#<pydoc>
def register_custom_data_type(dt):
"""
Registers a custom data type.
@param dt: an instance of the data_type_t class
@return:
< 0 if failed to register
> 0 data type id
"""
pass
#</pydoc>
*/
// Given a py.data_format_t object, this function will register a datatype
static int py_register_custom_data_type(PyObject *py_dt)
{
py_custom_data_type_t *inst = new py_custom_data_type_t();
int r = inst->register_dt(py_dt);
if ( r < 0 )
{
delete inst;
return r;
}
// Insert the instance to the map
py_dt_map[r] = inst;
return r;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def unregister_custom_data_type(dtid):
"""
Unregisters a custom data type.
@param dtid: the data type id
@return: Boolean
"""
pass
#</pydoc>
*/
static bool py_unregister_custom_data_type(int dtid)
{
py_custom_data_type_map_t::iterator it = py_dt_map.find(dtid);
// Maybe the user is trying to unregister a C api dt?
if ( it == py_dt_map.end() )
return unregister_custom_data_type(dtid);
py_custom_data_type_t *inst = it->second;
bool ok = inst->unregister_dt();
// Perhaps it was automatically unregistered because the idb was close?
if ( !ok )
{
// Is this type still registered with IDA?
// If not found then mark the context for deletion
ok = find_custom_data_type(inst->get_name()) < 0;
}
if ( ok )
{
py_dt_map.erase(it);
delete inst;
}
return ok;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def register_custom_data_format(dtid, df):
"""
Registers a custom data format with a given data type.
@param dtid: data type id
@param df: an instance of data_format_t
@return:
< 0 if failed to register
> 0 data format id
"""
pass
#</pydoc>
*/
static int py_register_custom_data_format(int dtid, PyObject *py_df)
{
py_custom_data_format_t *inst = new py_custom_data_format_t();
int r = inst->register_df(dtid, py_df);
if ( r < 0 )
{
delete inst;
return r;
}
// Insert the instance
py_df_list.add(dtid, r, inst);
return r;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def unregister_custom_data_format(dtid, dfid):
"""
Unregisters a custom data format
@param dtid: data type id
@param dfid: data format id
@return: Boolean
"""
pass
#</pydoc>
*/
static bool py_unregister_custom_data_format(int dtid, int dfid)
{
py_custom_data_format_list_t::POS pos;
py_custom_data_format_t *inst = py_df_list.find(dtid, dfid, &pos);
// Maybe the user is trying to unregister a C api data format?
if ( inst == NULL )
return unregister_custom_data_format(dtid, dfid);
bool ok = inst->unregister_df(dtid);
// Perhaps it was automatically unregistered because the type was unregistered?
if ( !ok )
{
// Is this format still registered with IDA?
// If not, mark the context for deletion
ok = find_custom_data_format(inst->get_name()) < 0;
}
if ( ok )
{
py_df_list.erase(pos);
delete inst;
}
return ok;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def get_custom_data_format(dtid, dfid):
"""
Returns a dictionary populated with the data format values or None on failure.
@param dtid: data type id
@param dfid: data format id
"""
pass
#</pydoc>
*/
// Get definition of a registered custom data format and returns a dictionary
static PyObject *py_get_custom_data_format(int dtid, int fid)
{
const data_format_t *df = get_custom_data_format(dtid, fid);
if ( df == NULL )
Py_RETURN_NONE;
return py_data_format_to_py_dict(df);
}
//------------------------------------------------------------------------
/*
#<pydoc>
def get_custom_data_type(dtid):
"""
Returns a dictionary populated with the data type values or None on failure.
@param dtid: data type id
"""
pass
#</pydoc>
*/
// Get definition of a registered custom data format and returns a dictionary
static PyObject *py_get_custom_data_type(int dtid)
{
const data_type_t *dt = get_custom_data_type(dtid);
if ( dt == NULL )
Py_RETURN_NONE;
return py_data_type_to_py_dict(dt);
}
//</inline(py_bytes)> //</inline(py_bytes)>
%} %}
%pythoncode %{
#<pycode(py_bytes)>
DTP_NODUP = 0x0001
class data_type_t(object):
"""
Custom data type definition. All data types should inherit from this class.
"""
def __init__(self, name, value_size = 0, menu_name = None, hotkey = None, asm_keyword = None, props = 0):
"""Please refer to bytes.hpp / data_type_t in the SDK"""
self.name = name
self.props = props
self.menu_name = menu_name
self.hotkey = hotkey
self.asm_keyword = asm_keyword
self.value_size = value_size
self.id = -1 # Will be initialized after registration
"""Contains the data type id after the data type is registered"""
def register(self):
"""Registers the data type and returns the type id or < 0 on failure"""
return _idaapi.register_custom_data_type(self)
def unregister(self):
"""Unregisters the data type and returns True on success"""
# Not registered?
if self.id < 0:
return True
# Try to unregister
r = _idaapi.unregister_custom_data_type(self.id)
# Clear the ID
if r:
self.id = -1
return r
#<pydoc>
# def may_create_at(self, ea, nbytes):
# """
# (optional) If this callback is not defined then this means always may create data type at the given ea.
# @param ea: address of the future item
# @param nbytes: size of the future item
# @return: Boolean
# """
#
# return False
#
# def calc_item_size(self, ea, maxsize):
# """
# (optional) If this callback is defined it means variable size datatype
# This function is used to determine size of the (possible) item at 'ea'
# @param ea: address of the item
# @param maxsize: maximal size of the item
# @return: integer
# Returns: 0-no such item can be created/displayed
# this callback is required only for varsize datatypes
# """
# return 0
#</pydoc>
# -----------------------------------------------------------------------
# Uncomment the corresponding callbacks in the inherited class
class data_format_t(object):
"""Information about a data format"""
def __init__(self, name, value_size = 0, menu_name = None, props = 0, hotkey = None, text_width = 0):
"""Custom data format definition.
@param name: Format name, must be unique
@param menu_name: Visible format name to use in menus
@param props: properties (currently 0)
@param hotkey: Hotkey for the corresponding menu item
@param value_size: size of the value in bytes. 0 means any size is ok
@text_width: Usual width of the text representation
"""
self.name = name
self.menu_name = menu_name
self.props = props
self.hotkey = hotkey
self.value_size = value_size
self.text_width = text_width
self.id = -1 # Will be initialized after registration
"""contains the format id after the format gets registered"""
def register(self, dtid):
"""Registers the data format with the given data type id and returns the type id or < 0 on failure"""
return _idaapi.register_custom_data_format(dtid, self)
def unregister(self, dtid):
"""Unregisters the data format with the given data type id"""
# Not registered?
if self.id < 0:
return True
# Unregister
r = _idaapi.unregister_custom_data_format(dtid, self.id)
# Clear the ID
if r:
self.id = -1
return r
#<pydoc>
# def printf(self, value, current_ea, operand_num, dtid):
# """
# Convert a value buffer to colored string.
#
# @param value: The value to be printed
# @param current_ea: The ea of the value
# @param operand_num: The affected operand
# @param dtid: custom data type id (0-standard built-in data type)
# @return: a colored string representing the passed 'value' or None on failure
# """
# return None
#
# def scan(self, input, current_ea, operand_num):
# """
# Convert from uncolored string 'input' to byte value
#
# @param input: input string
# @param current_ea: current address (BADADDR if unknown)
# @param operand_num: current operand number (-1 if unknown)
#
# @return: tuple (Boolean, string)
# - (False, ErrorMessage) if conversion fails
# - (True, Value buffer) if conversion succeeds
# """
# return (False, "Not implemented")
#
# def analyze(self, current_ea, operand_num):
# """
# (optional) Analyze custom data format occurrence.
# It can be used to create xrefs from the current item.
#
# @param current_ea: current address (BADADDR if unknown)
# @param operand_num: current operand number
# @return: None
# """
#
# pass
#</pydoc>
# -----------------------------------------------------------------------
def __walk_types_and_formats(formats, type_action, format_action):
broken = False
for f in formats:
if len(f) == 1:
if not format_action(f[0], 0):
broken = True
break
else:
dt = f[0]
dfs = f[1:]
if not type_action(dt):
broken = True
break
for df in dfs:
if not format_action(df, dt.id):
broken = True
break
return not broken
# -----------------------------------------------------------------------
def register_data_types_and_formats(formats):
"""
Registers multiple data types and formats at once.
To register one type/format at a time use register_custom_data_type/register_custom_data_format
It employs a special table of types and formats described below:
The 'formats' is a list of tuples. If a tuple has one element then it is the format to be registered with dtid=0
If the tuple has more than one element, then tuple[0] is the data type and tuple[1:] are the data formats. For example:
many_formats = [
(pascal_data_type(), pascal_data_format()),
(simplevm_data_type(), simplevm_data_format()),
(makedword_data_format(),),
(simplevm_data_format(),)
]
The first two tuples describe data types and their associated formats.
The last two tuples describe two data formats to be used with built-in data types.
"""
def __reg_format(df, dtid):
df.register(dtid)
if dtid == 0:
print "Registering format '%s' with built-in types, ID=%d" % (df.name, df.id)
else:
print " Registering format '%s', ID=%d (dtid=%d)" % (df.name, df.id, dtid)
return df.id != -1
def __reg_type(dt):
dt.register()
print "Registering type '%s', ID=%d" % (dt.name, dt.id)
return dt.id != -1
ok = __walk_types_and_formats(formats, __reg_type, __reg_format)
return 1 if ok else -1
# -----------------------------------------------------------------------
def unregister_data_types_and_formats(formats):
"""As opposed to register_data_types_and_formats(), this function
unregisters multiple data types and formats at once.
"""
def __unreg_format(df, dtid):
df.unregister(dtid)
print "%snregistering format '%s'" % ("U" if dtid == 0 else " u", df.name)
return True
def __unreg_type(dt):
print "Unregistering type '%s', ID=%d" % (dt.name, dt.id)
dt.unregister()
return True
ok = __walk_types_and_formats(formats, __unreg_type, __unreg_format)
return 1 if ok else -1
#</pycode(py_bytes)>
%}

View File

@ -1,263 +1,289 @@
// SWIG chokes on the original declaration so it is replicated here // SWIG chokes on the original declaration so it is replicated here
typedef struct typedef struct
{ {
ulonglong ival; // 8: integer value ulonglong ival; // 8: integer value
ushort fval[6]; // 12: floating point value in the internal representation (see ieee.h) ushort fval[6]; // 12: floating point value in the internal representation (see ieee.h)
} regval_t; } regval_t;
%ignore dbg; %ignore dbg;
%ignore get_manual_regions; %ignore get_manual_regions;
%rename (get_manual_regions) py_get_manual_regions; %ignore source_file_t;
%ignore set_manual_regions; %ignore source_item_t;
%include "dbg.hpp" %ignore srcinfo_provider_t;
%ignore DBG_Callback; %rename (get_manual_regions) py_get_manual_regions;
%feature("director") DBG_Hooks; %ignore set_manual_regions;
%include "dbg.hpp"
%{ %ignore DBG_Callback;
//<code(py_dbg)> %feature("director") DBG_Hooks;
static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas);
//</code(py_dbg)> %{
%} //<code(py_dbg)>
static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas);
%inline %{ //</code(py_dbg)>
%}
//<inline(py_dbg)>
//------------------------------------------------------------------------- %inline %{
static PyObject *py_get_manual_regions()
{ //<inline(py_dbg)>
meminfo_vec_t areas;
get_manual_regions(&areas); //-------------------------------------------------------------------------
return meminfo_vec_t_to_py(areas); /*
} #<pydoc>
def get_manual_regions():
//------------------------------------------------------------------------- """
static PyObject *refresh_debugger_memory() Returns the manual memory regions
{ @return: list(startEA, endEA, name, sclass, sbase, bitness, perm)
invalidate_dbgmem_config(); """
invalidate_dbgmem_contents(BADADDR, BADADDR); pass
if ( dbg != NULL && dbg->stopped_at_debug_event != NULL ) #</pydoc>
dbg->stopped_at_debug_event(true); */
Py_RETURN_NONE; static PyObject *py_get_manual_regions()
} {
//</inline(py_dbg)> meminfo_vec_t areas;
get_manual_regions(&areas);
int idaapi DBG_Callback(void *ud, int notification_code, va_list va); return meminfo_vec_t_to_py(areas);
class DBG_Hooks }
{
public: //-------------------------------------------------------------------------
virtual ~DBG_Hooks() {}; /*
#<pydoc>
bool hook() { return hook_to_notification_point(HT_DBG, DBG_Callback, this); }; def refresh_debugger_memory():
bool unhook() { return unhook_from_notification_point(HT_DBG, DBG_Callback, this); }; """
/* Hook functions to be overridden in Python */ Refreshes the debugger memory
virtual void dbg_process_start(pid_t pid, @return: Nothing
thid_t tid, """
ea_t ea, pass
char *name, #</pydoc>
ea_t base, */
asize_t size) { }; static PyObject *refresh_debugger_memory()
virtual void dbg_process_exit(pid_t pid, {
thid_t tid, invalidate_dbgmem_config();
ea_t ea, invalidate_dbgmem_contents(BADADDR, 0);
int exit_code) { }; if ( dbg != NULL && dbg->stopped_at_debug_event != NULL )
virtual void dbg_process_attach(pid_t pid, dbg->stopped_at_debug_event(true);
thid_t tid, isEnabled(0);
ea_t ea,
char *name, Py_RETURN_NONE;
ea_t base, }
asize_t size) { }; //</inline(py_dbg)>
virtual void dbg_process_detach(pid_t pid,
thid_t tid, int idaapi DBG_Callback(void *ud, int notification_code, va_list va);
ea_t ea) { }; class DBG_Hooks
virtual void dbg_thread_start(pid_t pid, {
thid_t tid, public:
ea_t ea) { }; virtual ~DBG_Hooks() {};
virtual void dbg_thread_exit(pid_t pid,
thid_t tid, bool hook() { return hook_to_notification_point(HT_DBG, DBG_Callback, this); };
ea_t ea, bool unhook() { return unhook_from_notification_point(HT_DBG, DBG_Callback, this); };
int exit_code) { }; /* Hook functions to be overridden in Python */
virtual void dbg_library_load(pid_t pid, virtual void dbg_process_start(pid_t pid,
thid_t tid, thid_t tid,
ea_t ea, ea_t ea,
char *name, char *name,
ea_t base, ea_t base,
asize_t size) { }; asize_t size) { };
virtual void dbg_library_unload(pid_t pid, virtual void dbg_process_exit(pid_t pid,
thid_t tid, thid_t tid,
ea_t ea, ea_t ea,
char *libname) { }; int exit_code) { };
virtual void dbg_information(pid_t pid, virtual void dbg_process_attach(pid_t pid,
thid_t tid, thid_t tid,
ea_t ea, ea_t ea,
char *info) { }; char *name,
virtual int dbg_exception(pid_t pid, ea_t base,
thid_t tid, asize_t size) { };
ea_t ea, virtual void dbg_process_detach(pid_t pid,
int code, thid_t tid,
bool can_cont, ea_t ea) { };
ea_t exc_ea, virtual void dbg_thread_start(pid_t pid,
char *info) { return 0; }; thid_t tid,
virtual void dbg_suspend_process(void) { }; ea_t ea) { };
virtual int dbg_bpt(thid_t tid, ea_t breakpoint_ea) { return 0; }; virtual void dbg_thread_exit(pid_t pid,
virtual int dbg_trace(thid_t tid, ea_t ip) { return 0; }; thid_t tid,
virtual void dbg_request_error(int failed_command, ea_t ea,
int failed_dbg_notification) { }; int exit_code) { };
virtual void dbg_step_into(void) { }; virtual void dbg_library_load(pid_t pid,
virtual void dbg_step_over(void) { }; thid_t tid,
virtual void dbg_run_to(thid_t tid) { }; ea_t ea,
virtual void dbg_step_until_ret(void) { }; char *name,
}; ea_t base,
asize_t size) { };
int idaapi DBG_Callback(void *ud, int notification_code, va_list va) virtual void dbg_library_unload(pid_t pid,
{ thid_t tid,
class DBG_Hooks *proxy = (class DBG_Hooks *)ud; ea_t ea,
char *libname) { };
debug_event_t *event; virtual void dbg_information(pid_t pid,
thid_t tid; thid_t tid,
int *warn; ea_t ea,
ea_t ip; char *info) { };
ea_t breakpoint_ea; virtual int dbg_exception(pid_t pid,
thid_t tid,
try { ea_t ea,
switch (notification_code) int code,
{ bool can_cont,
case dbg_process_start: ea_t exc_ea,
event = va_arg(va, debug_event_t *); char *info) { return 0; };
proxy->dbg_process_start(event->pid, virtual void dbg_suspend_process(void) { };
event->tid, virtual int dbg_bpt(thid_t tid, ea_t breakpoint_ea) { return 0; };
event->ea, virtual int dbg_trace(thid_t tid, ea_t ip) { return 0; };
event->modinfo.name, virtual void dbg_request_error(int failed_command,
event->modinfo.base, int failed_dbg_notification) { };
event->modinfo.size); virtual void dbg_step_into(void) { };
return 0; virtual void dbg_step_over(void) { };
case dbg_process_exit: virtual void dbg_run_to(thid_t tid) { };
event = va_arg(va, debug_event_t *); virtual void dbg_step_until_ret(void) { };
proxy->dbg_process_exit(event->pid, };
event->tid,
event->ea, int idaapi DBG_Callback(void *ud, int notification_code, va_list va)
event->exit_code); {
return 0; class DBG_Hooks *proxy = (class DBG_Hooks *)ud;
case dbg_process_attach: debug_event_t *event;
event = va_arg(va, debug_event_t *); thid_t tid;
proxy->dbg_process_attach(event->pid, int *warn;
event->tid, ea_t ip;
event->ea, ea_t breakpoint_ea;
event->modinfo.name,
event->modinfo.base, try {
event->modinfo.size); switch (notification_code)
return 0; {
case dbg_process_start:
case dbg_process_detach: event = va_arg(va, debug_event_t *);
event = va_arg(va, debug_event_t *); proxy->dbg_process_start(event->pid,
proxy->dbg_process_detach(event->pid, event->tid,
event->tid, event->ea,
event->ea); event->modinfo.name,
return 0; event->modinfo.base,
event->modinfo.size);
case dbg_thread_start: return 0;
event = va_arg(va, debug_event_t *); case dbg_process_exit:
proxy->dbg_thread_start(event->pid, event = va_arg(va, debug_event_t *);
event->tid, proxy->dbg_process_exit(event->pid,
event->ea); event->tid,
return 0; event->ea,
event->exit_code);
case dbg_thread_exit: return 0;
event = va_arg(va, debug_event_t *);
proxy->dbg_thread_exit(event->pid, case dbg_process_attach:
event->tid, event = va_arg(va, debug_event_t *);
event->ea, proxy->dbg_process_attach(event->pid,
event->exit_code); event->tid,
return 0; event->ea,
event->modinfo.name,
case dbg_library_load: event->modinfo.base,
event = va_arg(va, debug_event_t *); event->modinfo.size);
proxy->dbg_library_load(event->pid, return 0;
event->tid,
event->ea, case dbg_process_detach:
event->modinfo.name, event = va_arg(va, debug_event_t *);
event->modinfo.base, proxy->dbg_process_detach(event->pid,
event->modinfo.size); event->tid,
return 0; event->ea);
return 0;
case dbg_library_unload:
event = va_arg(va, debug_event_t *); case dbg_thread_start:
proxy->dbg_library_unload(event->pid, event = va_arg(va, debug_event_t *);
event->tid, proxy->dbg_thread_start(event->pid,
event->ea, event->tid,
event->info); event->ea);
return 0; return 0;
case dbg_information: case dbg_thread_exit:
event = va_arg(va, debug_event_t *); event = va_arg(va, debug_event_t *);
proxy->dbg_information(event->pid, proxy->dbg_thread_exit(event->pid,
event->tid, event->tid,
event->ea, event->ea,
event->info); event->exit_code);
return 0; return 0;
case dbg_exception: case dbg_library_load:
event = va_arg(va, debug_event_t *); event = va_arg(va, debug_event_t *);
warn = va_arg(va, int *); proxy->dbg_library_load(event->pid,
*warn = proxy->dbg_exception(event->pid, event->tid,
event->tid, event->ea,
event->ea, event->modinfo.name,
event->exc.code, event->modinfo.base,
event->exc.can_cont, event->modinfo.size);
event->exc.ea, return 0;
event->exc.info);
return 0; case dbg_library_unload:
event = va_arg(va, debug_event_t *);
case dbg_suspend_process: proxy->dbg_library_unload(event->pid,
proxy->dbg_suspend_process(); event->tid,
return 0; event->ea,
event->info);
case dbg_bpt: return 0;
tid = va_arg(va, thid_t);
breakpoint_ea = va_arg(va, ea_t); case dbg_information:
warn = va_arg(va, int *); event = va_arg(va, debug_event_t *);
*warn = proxy->dbg_bpt(tid, breakpoint_ea); proxy->dbg_information(event->pid,
return 0; event->tid,
event->ea,
case dbg_trace: event->info);
tid = va_arg(va, thid_t); return 0;
ip = va_arg(va, ea_t);
return proxy->dbg_bpt(tid, ip); case dbg_exception:
event = va_arg(va, debug_event_t *);
case dbg_request_error: warn = va_arg(va, int *);
{ *warn = proxy->dbg_exception(event->pid,
int failed_command = (int)va_arg(va, ui_notification_t); event->tid,
int failed_dbg_notification = (int)va_arg(va, dbg_notification_t); event->ea,
proxy->dbg_request_error(failed_command, failed_dbg_notification); event->exc.code,
return 0; event->exc.can_cont,
} event->exc.ea,
case dbg_step_into: event->exc.info);
proxy->dbg_step_into(); return 0;
return 0;
case dbg_suspend_process:
case dbg_step_over: proxy->dbg_suspend_process();
proxy->dbg_step_over(); return 0;
return 0;
case dbg_bpt:
case dbg_run_to: tid = va_arg(va, thid_t);
tid = va_arg(va, thid_t); breakpoint_ea = va_arg(va, ea_t);
proxy->dbg_run_to(tid); warn = va_arg(va, int *);
return 0; *warn = proxy->dbg_bpt(tid, breakpoint_ea);
return 0;
case dbg_step_until_ret:
proxy->dbg_step_until_ret(); case dbg_trace:
return 0; tid = va_arg(va, thid_t);
} ip = va_arg(va, ea_t);
} return proxy->dbg_bpt(tid, ip);
catch (Swig::DirectorException &)
{ case dbg_request_error:
msg("Exception in IDP Hook function:\n"); {
if (PyErr_Occurred()) int failed_command = (int)va_argi(va, ui_notification_t);
{ int failed_dbg_notification = (int)va_argi(va, dbg_notification_t);
PyErr_Print(); proxy->dbg_request_error(failed_command, failed_dbg_notification);
} return 0;
} }
return 0; case dbg_step_into:
} proxy->dbg_step_into();
return 0;
%}
case dbg_step_over:
proxy->dbg_step_over();
return 0;
case dbg_run_to:
tid = va_arg(va, thid_t);
proxy->dbg_run_to(tid);
return 0;
case dbg_step_until_ret:
proxy->dbg_step_until_ret();
return 0;
}
}
catch (Swig::DirectorException &)
{
msg("Exception in IDP Hook function:\n");
if (PyErr_Occurred())
{
PyErr_Print();
}
}
return 0;
}
%}

View File

@ -60,6 +60,96 @@ int idaapi py_enumerate_files_cb(const char *file, void *ud)
%inline %{ %inline %{
//<inline(py_diskio)> //<inline(py_diskio)>
/*
#<pydoc>
class loader_input_t(pyidc_opaque_object_t):
"""A helper class to work with linput_t related functions.
This class is also used by file loaders scripts.
"""
def __init__(self):
pass
def close(self):
"""Closes the file"""
pass
def open(self, filename, remote = False):
"""Opens a file (or a remote file)
@return: Boolean
"""
pass
def set_linput(self, linput):
"""Links the current loader_input_t instance to a linput_t instance"""
pass
@staticmethod
def from_fp(fp):
"""A static method to construct an instance from a FILE*"""
pass
def open_memory(self, start, size):
"""Create a linput for process memory (By internally calling idaapi.create_memory_linput())
This linput will use dbg->read_memory() to read data
@param start: starting address of the input
@param size: size of the memory area to represent as linput
if unknown, may be passed as 0
"""
pass
def seek(self, pos, whence = SEEK_SET):
"""Set input source position
@return: the new position (not 0 as fseek!)
"""
pass
def tell(self):
"""Returns the current position"""
pass
def getz(self, sz, fpos = -1):
"""Returns a zero terminated string at the given position
@param sz: maximum size of the string
@param fpos: if != -1 then seek will be performed before reading
@return: The string or None on failure.
"""
pass
def gets(self, len):
"""Reads a line from the input file. Returns the read line or None"""
pass
def read(self, size):
"""Reads from the file. Returns the buffer or None"""
pass
def readbytes(self, size, big_endian):
"""Similar to read() but it respect the endianness"""
pass
def file2base(self, pos, ea1, ea2, patchable):
"""
Load portion of file into the database
This function will include (ea1..ea2) into the addressing space of the
program (make it enabled)
@param li: pointer ot input source
@param pos: position in the file
@param (ea1..ea2): range of destination linear addresses
@param patchable: should the kernel remember correspondance of
file offsets to linear addresses.
@return: 1-ok,0-read error, a warning is displayed
"""
pass
def get_char(self):
"""Reads a single character from the file. Returns None if EOF or the read character"""
pass
def opened(self):
"""Checks if the file is opened or not"""
pass
#</pydoc>
*/
class loader_input_t class loader_input_t
{ {
private: private:
@ -126,17 +216,17 @@ public:
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
PyObject *open(const char *filename, bool remote = false) bool open(const char *filename, bool remote = false)
{ {
close(); close();
li = open_linput(filename, remote); li = open_linput(filename, remote);
if ( li == NULL ) if ( li == NULL )
Py_RETURN_FALSE; return false;
// Save file name // Save file name
fn = filename; fn = filename;
own = OWN_CREATE; own = OWN_CREATE;
Py_RETURN_TRUE; return true;
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -188,16 +278,16 @@ public:
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
PyObject *open_memory(ea_t start, asize_t size = 0) bool open_memory(ea_t start, asize_t size = 0)
{ {
linput_t *l = create_memory_linput(start, size); linput_t *l = create_memory_linput(start, size);
if ( l == NULL ) if ( l == NULL )
Py_RETURN_FALSE; return false;
close(); close();
li = l; li = l;
fn = "<memory>"; fn = "<memory>";
own = OWN_CREATE; own = OWN_CREATE;
Py_RETURN_TRUE; return true;
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
@ -326,6 +416,23 @@ public:
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
/*
#<pydoc>
def enumerate_files(path, fname, callback):
"""
Enumerate files in the specified directory while the callback returns 0.
@param path: directory to enumerate files in
@param fname: mask of file names to enumerate
@param callback: a callable object that takes the filename as
its first argument and it returns 0 to continue
enumeration or non-zero to stop enumeration.
@return:
None in case of script errors
tuple(code, fname) : If the callback returns non-zero
"""
pass
#</pydoc>
*/
PyObject *py_enumerate_files(PyObject *path, PyObject *fname, PyObject *callback) PyObject *py_enumerate_files(PyObject *path, PyObject *fname, PyObject *callback)
{ {
do do
@ -349,6 +456,7 @@ PyObject *py_enumerate_files(PyObject *path, PyObject *fname, PyObject *callback
%pythoncode %{ %pythoncode %{
#<pycode(py_diskio)> #<pycode(py_diskio)>
def enumerate_system_files(subdir, fname, callback): def enumerate_system_files(subdir, fname, callback):
"""Similar to enumerate_files() however it searches inside IDA directory or its subdirectories"""
return enumerate_files(idadir(subdir), fname, callback) return enumerate_files(idadir(subdir), fname, callback)
#</pycode(py_diskio)> #</pycode(py_diskio)>
%} %}

View File

@ -1,29 +1,29 @@
// Kernel only & unexported symbols // Kernel only & unexported symbols
%ignore enums; %ignore enums;
%ignore init_enums; %ignore init_enums;
%ignore save_enums; %ignore save_enums;
%ignore term_enums; %ignore term_enums;
%ignore set_enum_flag; %ignore set_enum_flag;
%ignore sync_from_enum;; %ignore sync_from_enum;;
%ignore del_all_consts; %ignore del_all_enum_members;
%ignore get_selected_enum; %ignore get_selected_enum;
%ignore add_selected_enum; %ignore add_selected_enum;
%ignore unmark_selected_enums; %ignore unmark_selected_enums;
%ignore is_good_bmask; %ignore is_good_bmask;
%ignore get_bmask_enum; %ignore get_bmask_enum;
%ignore ENUM_REVERSE; %ignore ENUM_REVERSE;
%ignore ENUM_SELMEMS; %ignore ENUM_SELMEMS;
%ignore ENUM_QTY_IDX; %ignore ENUM_QTY_IDX;
%ignore ENUM_FLG_IDX; %ignore ENUM_FLG_IDX;
%ignore ENUM_FLAGS; %ignore ENUM_FLAGS;
%ignore ENUM_FLAGS_IS_BF; %ignore ENUM_FLAGS_IS_BF;
%ignore ENUM_FLAGS_HIDDEN; %ignore ENUM_FLAGS_HIDDEN;
%ignore ENUM_MASKS; %ignore ENUM_MASKS;
%ignore ENUM_MEMBERS; %ignore ENUM_MEMBERS;
%ignore CONST_ENUM; %ignore CONST_ENUM;
%ignore CONST_VALUE; %ignore CONST_VALUE;
%ignore CONST_BMASK; %ignore CONST_BMASK;
%ignore CONST_SERIAL; %ignore CONST_SERIAL;
%ignore CONST_SERIALS; %ignore CONST_SERIALS;
%include "enum.hpp" %include "enum.hpp"

View File

@ -7,8 +7,20 @@
%ignore register_extlang; %ignore register_extlang;
%ignore IDCFuncs; %ignore IDCFuncs;
%ignore set_idc_func; %ignore set_idc_func;
%ignore set_idc_func_ex;
%ignore VarLong; %ignore VarLong;
%ignore VarNum; %ignore VarNum;
%ignore extlang_get_attr_exists;
%ignore extlang_create_object_exists;
%ignore create_script_object;
%ignore set_script_attr;
%ignore set_attr_exists;
%ignore get_script_attr;
%ignore extlang_get_attr_exists;
%ignore extlang_compile_file;
%ignore get_extlangs;
%ignore create_idc_object;
%ignore run_script_func;
%ignore VarString; %ignore VarString;
%ignore VarFloat; %ignore VarFloat;
%ignore VarFree; %ignore VarFree;

View File

@ -1,5 +1,79 @@
%inline %{ %inline %{
//<inline(py_qfile)> //<inline(py_qfile)>
/*
#<pydoc>
class qfile_t(pyidc_opaque_object_t):
"""A helper class to work with FILE related functions."""
def __init__(self):
pass
def close(self):
"""Closes the file"""
pass
def open(self, filename, mode):
"""Opens a file
@param filename: the file name
@param mode: The mode string, ala fopen() style
@return: Boolean
"""
pass
def set_linput(self, linput):
"""Links the current loader_input_t instance to a linput_t instance"""
pass
@staticmethod
def tmpfile():
"""A static method to construct an instance using a temporary file"""
pass
def seek(self, pos, whence = SEEK_SET):
"""Set input source position
@return: the new position (not 0 as fseek!)
"""
pass
def tell(self):
"""Returns the current position"""
pass
def gets(self, len):
"""Reads a line from the input file. Returns the read line or None"""
pass
def read(self, size):
"""Reads from the file. Returns the buffer or None"""
pass
def write(self, buf):
"""Writes to the file. Returns 0 or the number of bytes written"""
pass
def readbytes(self, size, big_endian):
"""Similar to read() but it respect the endianness"""
pass
def writebytes(self, size, big_endian):
"""Similar to write() but it respect the endianness"""
pass
def flush(self):
pass
def get_char(self):
"""Reads a single character from the file. Returns None if EOF or the read character"""
pass
def put_char(self):
"""Writes a single character to the file"""
pass
def opened(self):
"""Checks if the file is opened or not"""
pass
#</pydoc>
*/
class qfile_t class qfile_t
{ {
private: private:
@ -71,16 +145,16 @@ public:
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
PyObject *open(const char *filename, const char *mode) bool open(const char *filename, const char *mode)
{ {
close(); close();
fp = qfopen(filename, mode); fp = qfopen(filename, mode);
if ( fp == NULL ) if ( fp == NULL )
Py_RETURN_FALSE; return false;
// Save file name // Save file name
fn = filename; fn = filename;
own = true; own = true;
Py_RETURN_TRUE; return true;
} }
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------

View File

@ -16,5 +16,15 @@
%ignore read_stkpnts; %ignore read_stkpnts;
%ignore write_stkpnts; %ignore write_stkpnts;
%ignore del_stkpnts; %ignore del_stkpnts;
%ignore rename_frame;
%ignore get_stkvar;
%rename (get_stkvar) py_get_stkvar;
%ignore add_stkvar3;
%rename (add_stkvar3) py_add_stkvar3;
%ignore calc_frame_offset;
%ignore add_stkvar;
%include "frame.hpp" %include "frame.hpp"

View File

@ -1,45 +1,51 @@
%cstring_bounded_output_none(char *buf, MAXSTR); %cstring_bounded_output_none(char *buf, MAXSTR);
%cstring_bounded_output_none(char *optlibs, MAXSTR); %cstring_bounded_output_none(char *optlibs, MAXSTR);
// FIXME: Are these really useful? // FIXME: Are these really useful?
%ignore iterate_func_chunks; %ignore iterate_func_chunks;
%ignore get_idasgn_desc; %ignore get_idasgn_desc;
%ignore get_idasgn_header_by_short_name; %ignore get_idasgn_header_by_short_name;
// Kernel-only & unexported symbols // Kernel-only & unexported symbols
%ignore del_regargs; %ignore del_regargs;
%ignore write_regargs; %ignore write_regargs;
%ignore find_regarg; %ignore find_regarg;
%ignore free_regarg; %ignore free_regarg;
%ignore determine_rtl; %ignore determine_rtl;
%ignore init_signatures; %ignore init_signatures;
%ignore save_signatures; %ignore save_signatures;
%ignore term_signatures; %ignore term_signatures;
%ignore init_funcs; %ignore init_funcs;
%ignore save_funcs; %ignore save_funcs;
%ignore term_funcs; %ignore term_funcs;
%ignore move_funcs; %ignore move_funcs;
%ignore copy_noret_info; %ignore copy_noret_info;
%ignore recalc_func_noret_flag; %ignore recalc_func_noret_flag;
%ignore plan_for_noret_analysis; %ignore plan_for_noret_analysis;
%ignore invalidate_sp_analysis; %ignore invalidate_sp_analysis;
%ignore create_func_eas_array; %ignore create_func_eas_array;
%ignore auto_add_func_tails; %ignore auto_add_func_tails;
%ignore read_tails; %ignore read_tails;
%include "funcs.hpp" %include "funcs.hpp"
%clear(char *buf); %clear(char *buf);
%clear(char *optlibs); %clear(char *optlibs);
%inline %{ %inline %{
ea_t get_fchunk_referer(ea_t ea, size_t idx) /*
{ #<pydoc>
func_t *pfn = get_fchunk(ea); def get_fchunk_referer(ea, idx):
func_parent_iterator_t dummy(pfn); // read referer info pass
if (idx >= pfn->refqty || pfn->referers == NULL) #</pydoc>
return BADADDR; */
return pfn->referers[idx]; ea_t get_fchunk_referer(ea_t ea, size_t idx)
} {
%} func_t *pfn = get_fchunk(ea);
func_parent_iterator_t dummy(pfn); // read referer info
if (idx >= pfn->refqty || pfn->referers == NULL)
return BADADDR;
return pfn->referers[idx];
}
%}

View File

@ -1,101 +1,106 @@
%ignore cancellable_graph_t::check_cancel; %ignore cancellable_graph_t::check_cancel;
%ignore gdl_graph_t::gen_gdl; %ignore gdl_graph_t::gen_gdl;
%ignore gdl_graph_t::gen_gdl; %ignore gdl_graph_t::gen_gdl;
%ignore gdl_graph_t::path; %ignore gdl_graph_t::path;
%ignore gdl_graph_t::path_exists; %ignore gdl_graph_t::path_exists;
%ignore intmap_t::dstr; %ignore gdl_graph_t::gen_dot;
%ignore intmap_t::print;
%ignore intseq_t::add_block; %ignore intmap_t::dstr;
%ignore intseq_t::add_unique; %ignore intmap_t::print;
%ignore intseq_t::del; %ignore intseq_t::add_block;
%ignore intseq_t::dstr; %ignore intseq_t::add_unique;
%ignore intseq_t::print; %ignore intseq_t::del;
%ignore intseq_t::remove_block; %ignore intseq_t::dstr;
%ignore intset_t::dstr; %ignore intseq_t::print;
%ignore intset_t::print; %ignore intseq_t::remove_block;
%ignore node_set_t::add; %ignore intset_t::dstr;
%ignore node_set_t::extract; %ignore intset_t::print;
%ignore node_set_t::intersect; %ignore node_set_t::add;
%ignore node_set_t::node_set_t; %ignore node_set_t::extract;
%ignore node_set_t::sub; %ignore node_set_t::intersect;
%ignore qflow_chart_t::blocks; %ignore node_set_t::node_set_t;
%ignore flow_chart_t; %ignore node_set_t::sub;
%ignore setup_graph_subsystem; %ignore qflow_chart_t::blocks;
%ignore qbasic_block_t::succ; %ignore flow_chart_t;
%ignore qbasic_block_t::pred; %ignore default_graph_format;
%ignore setup_graph_subsystem;
%include "gdl.hpp" %ignore qbasic_block_t::succ;
%ignore qbasic_block_t::pred;
%extend qflow_chart_t
{ %include "gdl.hpp"
qbasic_block_t *__getitem__(int n)
{ %extend qflow_chart_t
return &(self->blocks[n]); {
} qbasic_block_t *__getitem__(int n)
} {
return &(self->blocks[n]);
%pythoncode %{ }
#<pycode(py_gdl)> }
# -----------------------------------------------------------------------
class BasicBlock: %pythoncode %{
def __init__(self, id, bb, f): #<pycode(py_gdl)>
self._f = f # -----------------------------------------------------------------------
self.id = id class BasicBlock:
"""Basic block ID""" """Basic block class. It is returned by the Flowchart class"""
self.startEA = bb.startEA def __init__(self, id, bb, f):
"""startEA of basic block""" self._f = f
self.endEA = bb.endEA self.id = id
"""endEA of basic block""" """Basic block ID"""
self.type = self._f._q.calc_block_type(self.id) self.startEA = bb.startEA
"""Block type (check fc_block_type_t enum)""" """startEA of basic block"""
self.endEA = bb.endEA
def preds(self): """endEA of basic block"""
""" self.type = self._f._q.calc_block_type(self.id)
Iterates the predecessors list """Block type (check fc_block_type_t enum)"""
"""
q = self._f._q def preds(self):
for i in xrange(0, self._f._q.npred(self.id)): """
yield self._f[q.pred(self.id, i)] Iterates the predecessors list
"""
def succs(self): q = self._f._q
""" for i in xrange(0, self._f._q.npred(self.id)):
Iterates the successors list yield self._f[q.pred(self.id, i)]
"""
q = self._f._q def succs(self):
for i in xrange(0, q.nsucc(self.id)): """
yield self._f[q.succ(self.id, i)] Iterates the successors list
"""
# ----------------------------------------------------------------------- q = self._f._q
class FlowChart: for i in xrange(0, q.nsucc(self.id)):
""" yield self._f[q.succ(self.id, i)]
Flowchart class used to determine basic blocks
""" # -----------------------------------------------------------------------
def __init__(self, f=None, bounds=None, flags=0): class FlowChart:
""" """
Constructor Flowchart class used to determine basic blocks.
@param f: A func_t type, use get_func(ea) to get a reference Check ex_gdl_qflow_chart.py for sample usage.
@param bounds: A tuple of the form (start, end). Used if "f" is None """
@param flags: one of the FC_xxxx flags. One interesting flag is FC_PREDS def __init__(self, f=None, bounds=None, flags=0):
""" """
if (not f) and (not bounds or type(bounds) != types.TupleType): Constructor
raise Exception("Please specifiy either a function or start/end pair") @param f: A func_t type, use get_func(ea) to get a reference
if not bounds: @param bounds: A tuple of the form (start, end). Used if "f" is None
bounds = (BADADDR, BADADDR) @param flags: one of the FC_xxxx flags. One interesting flag is FC_PREDS
# create the flowchart """
self._q = qflow_chart_t("", f, bounds[0], bounds[1], flags) if (not f) and (not bounds or type(bounds) != types.TupleType):
self.size = self._q.size() raise Exception("Please specifiy either a function or start/end pair")
if not bounds:
def refresh(): bounds = (BADADDR, BADADDR)
self._q.refresh() # create the flowchart
self.size = self._q.size() self._q = qflow_chart_t("", f, bounds[0], bounds[1], flags)
self.size = self._q.size()
def __getitem__(self, index):
""" def refresh():
Returns a basic block self._q.refresh()
@return: BasicBlock self.size = self._q.size()
"""
if index >= self.size: def __getitem__(self, index):
raise StopIteration """
return BasicBlock(index, self._q[index], self) Returns a basic block
#</pycode(py_gdl)> @return: BasicBlock
%} """
if index >= self.size:
raise StopIteration
return BasicBlock(index, self._q[index], self)
#</pycode(py_gdl)>
%}

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +1,23 @@
// Ignore kernel-only symbols // Ignore kernel-only symbols
%ignore dual_text_options_t; %ignore dual_text_options_t;
%ignore idainfo::init; %ignore idainfo::init;
%ignore idainfo::retrieve; %ignore idainfo::retrieve;
%ignore idainfo::read; %ignore idainfo::read;
%ignore idainfo::write; %ignore idainfo::write;
%ignore idainfo::align_short_demnames; %ignore idainfo::align_short_demnames;
%ignore idainfo::align_strtype; %ignore idainfo::align_strtype;
%ignore idainfo::align_long_demnames; %ignore idainfo::align_long_demnames;
%ignore setflag(uchar &where,uchar bit,int value); %ignore setflag(uchar &where,uchar bit,int value);
%ignore setflag(ushort &where,ushort bit,int value); %ignore setflag(ushort &where,ushort bit,int value);
%ignore setflag(uint32 &where,uint32 bit,int value); %ignore setflag(uint32 &where,uint32 bit,int value);
// Make idainfo::get_proc_name() work // Make idainfo::get_proc_name() work
%cstring_bounded_output(char *buf, 8); %cstring_bounded_output(char *buf, 8);
%ignore BADADDR; %ignore BADADDR;
%ignore BADSEL; %ignore BADSEL;
%include "ida.hpp" %include "ida.hpp"
%clear(char *buf); %clear(char *buf);

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
%ignore memory_info_t; %ignore memory_info_t;
%ignore register_info_t; %ignore register_info_t;
%ignore appcall; %ignore appcall;
%ignore gdecode_t;
%apply unsigned char { char dtyp }; %apply unsigned char { char dtyp };
%include "idd.hpp" %include "idd.hpp"
@ -16,7 +17,7 @@ static bool dbg_can_query()
{ {
// Reject the request only if no debugger is set // Reject the request only if no debugger is set
// or the debugger cannot be queried while not in suspended state // or the debugger cannot be queried while not in suspended state
return !(dbg == NULL || (!dbg->may_disturb() && get_process_state() > DSTATE_SUSP)); return dbg != NULL && (dbg->may_disturb() || get_process_state() < DSTATE_NOTASK);
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -42,116 +43,6 @@ static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas)
return py_list; return py_list;
} }
//-------------------------------------------------------------------------
PyObject *dbg_get_memory_info()
{
if (!dbg_can_query())
Py_RETURN_NONE;
// Invalidate memory
invalidate_dbgmem_config();
invalidate_dbgmem_contents(BADADDR, BADADDR);
meminfo_vec_t areas;
dbg->get_memory_info(areas);
return meminfo_vec_t_to_py(areas);
}
//-------------------------------------------------------------------------
PyObject *dbg_get_registers()
{
if (dbg == NULL)
Py_RETURN_NONE;
PyObject *py_list = PyList_New(dbg->registers_size);
for (int i=0;i<dbg->registers_size;i++)
{
register_info_t &ri = dbg->registers[i];
PyObject *py_bits;
// Does this register have bit strings?
if (ri.bit_strings != NULL)
{
int nbits = (int)b2a_width((int)get_dtyp_size(ri.dtyp), 0) * 4;
py_bits = PyList_New(nbits);
for (int i=0;i<nbits;i++)
{
const char *s = ri.bit_strings[i];
PyList_SetItem(py_bits, i, PyString_FromString(s == NULL ? "" : s));
}
}
else
{
Py_INCREF(Py_None);
py_bits = Py_None;
}
// name flags class dtyp bit_strings bit_strings_default_mask
PyList_SetItem(py_list, i,
Py_BuildValue("(sIIINI)",
ri.name,
ri.flags,
(unsigned int)ri.register_class,
(unsigned int)ri.dtyp,
py_bits,
(unsigned int)ri.bit_strings_default));
}
return py_list;
}
//-------------------------------------------------------------------------
PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_value)
{
if (!dbg_can_query() || !PyInt_Check(py_tid) || !PyInt_Check(py_sreg_value))
Py_RETURN_NONE;
ea_t answer;
thid_t tid = PyInt_AsLong(py_tid);
int sreg_value = PyInt_AsLong(py_sreg_value);
if (dbg->thread_get_sreg_base(tid, sreg_value, &answer) != 1)
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, pyul_t(answer));
}
//-------------------------------------------------------------------------
PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz)
{
uint64 ea, sz;
if ( !dbg_can_query() || !PyGetNumber(py_ea, &ea) || !PyGetNumber(py_sz, &sz) )
Py_RETURN_NONE;
char *buf = new char[size_t(sz)];
if ( buf == NULL )
Py_RETURN_NONE;
PyObject *ret;
if ( (size_t)dbg->read_memory(ea_t(ea), buf, size_t(sz)) == sz )
{
ret = PyString_FromStringAndSize(buf, (Py_ssize_t)sz);
}
else
{
Py_INCREF(Py_None);
ret = Py_None;
}
delete [] buf;
return ret;
}
//-------------------------------------------------------------------------
PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf)
{
uint64 ea;
if ( !dbg_can_query() || !PyString_Check(py_buf) || !PyGetNumber(py_ea, &ea) )
Py_RETURN_NONE;
size_t sz = PyString_GET_SIZE(py_buf);
void *buf = (void *)PyString_AS_STRING(py_buf);
if ( dbg->write_memory(ea_t(ea), buf, sz) != sz )
Py_RETURN_FALSE;
Py_RETURN_TRUE;
}
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
PyObject *py_appcall( PyObject *py_appcall(
ea_t func_ea, ea_t func_ea,
@ -202,7 +93,7 @@ PyObject *py_appcall(
msg("input variables:\n" msg("input variables:\n"
"----------------\n"); "----------------\n");
qstring s; qstring s;
for (Py_ssize_t i=0;i<nargs;i++) for ( Py_ssize_t i=0; i<nargs; i++ )
{ {
VarPrint(&s, &idc_args[i]); VarPrint(&s, &idc_args[i]);
msg("%d]\n%s\n-----------\n", int(i), s.c_str()); msg("%d]\n%s\n-----------\n", int(i), s.c_str());
@ -220,10 +111,10 @@ PyObject *py_appcall(
idc_args.begin(), idc_args.begin(),
&idc_result); &idc_result);
if (ret != eOk) if ( ret != eOk )
{ {
// An exception was thrown? // An exception was thrown?
if (ret == eExecThrow) if ( ret == eExecThrow )
{ {
// Convert the result (which is a debug_event) into a Python object // Convert the result (which is a debug_event) into a Python object
PyObject *py_appcall_exc(NULL); PyObject *py_appcall_exc(NULL);
@ -247,7 +138,7 @@ PyObject *py_appcall(
msg("return variables:\n" msg("return variables:\n"
"-----------------\n"); "-----------------\n");
qstring s; qstring s;
for (Py_ssize_t i=0;i<nargs;i++) for ( Py_ssize_t i=0; i<nargs; i++ )
{ {
VarPrint(&s, &idc_args[i]); VarPrint(&s, &idc_args[i]);
msg("%d]\n%s\n-----------\n", int(i), s.c_str()); msg("%d]\n%s\n-----------\n", int(i), s.c_str());
@ -255,13 +146,13 @@ PyObject *py_appcall(
} }
} }
// Convert IDC values back to Python values // Convert IDC values back to Python values
for (Py_ssize_t i=0;i<nargs;i++) for ( Py_ssize_t i=0; i<nargs; i++ )
{ {
// Get argument // Get argument
PyObject *py_item = PyList_GetItem(arg_list, i); PyObject *py_item = PyList_GetItem(arg_list, i);
// We convert arguments but fail only on fatal errors // We convert arguments but fail only on fatal errors
// (we ignore failure because of immutable objects) // (we ignore failure because of immutable objects)
if (idcvar_to_pyvar(idc_args[i], &py_item) == CIP_FAILED) if ( idcvar_to_pyvar(idc_args[i], &py_item) == CIP_FAILED )
{ {
PyErr_SetString(PyExc_ValueError, "PyAppCall: Failed while converting IDC values to Python values"); PyErr_SetString(PyExc_ValueError, "PyAppCall: Failed while converting IDC values to Python values");
return NULL; return NULL;
@ -269,7 +160,7 @@ PyObject *py_appcall(
} }
// Convert the result from IDC back to Python // Convert the result from IDC back to Python
PyObject *py_result(NULL); PyObject *py_result(NULL);
if (idcvar_to_pyvar(idc_result, &py_result) <= CIP_IMMUTABLE) if ( idcvar_to_pyvar(idc_result, &py_result) <= CIP_IMMUTABLE )
{ {
PyErr_SetString(PyExc_ValueError, "PyAppCall: Failed while converting IDC return value to Python return value"); PyErr_SetString(PyExc_ValueError, "PyAppCall: Failed while converting IDC return value to Python return value");
return NULL; return NULL;
@ -293,11 +184,165 @@ PyObject *py_appcall(
%inline %{ %inline %{
//<inline(py_idd)> //<inline(py_idd)>
PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf);
PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz); //-------------------------------------------------------------------------
PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_value); /*
PyObject *dbg_get_registers(); #<pydoc>
PyObject *dbg_get_memory_info(); def dbg_get_registers():
"""
This function returns the register definition from the currently loaded debugger.
Basically, it returns an array of structure similar to to idd.hpp / register_info_t
@return:
None if no debugger is loaded
tuple(name, flags, class, dtyp, bit_strings, bit_strings_default_mask)
The bit_strings can be a tuple of strings or None (if the register does not have bit_strings)
"""
pass
#</pydoc>
*/
static PyObject *dbg_get_registers()
{
if ( dbg == NULL )
Py_RETURN_NONE;
PyObject *py_list = PyList_New(dbg->registers_size);
for ( int i=0; i<dbg->registers_size; i++ )
{
register_info_t &ri = dbg->registers[i];
PyObject *py_bits;
// Does this register have bit strings?
if ( ri.bit_strings != NULL )
{
int nbits = (int)b2a_width((int)get_dtyp_size(ri.dtyp), 0) * 4;
py_bits = PyList_New(nbits);
for ( int i=0; i<nbits; i++ )
{
const char *s = ri.bit_strings[i];
PyList_SetItem(py_bits, i, PyString_FromString(s == NULL ? "" : s));
}
}
else
{
Py_INCREF(Py_None);
py_bits = Py_None;
}
// name, flags, class, dtyp, bit_strings, bit_strings_default_mask
PyList_SetItem(py_list, i,
Py_BuildValue("(sIIINI)",
ri.name,
ri.flags,
(unsigned int)ri.register_class,
(unsigned int)ri.dtyp,
py_bits,
(unsigned int)ri.bit_strings_default));
}
return py_list;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def dbg_get_thread_sreg_base(tid, sreg_value):
"""
Returns the segment register base value
@param tid: thread id
@param sreg_value: segment register (selector) value
@return:
- The base as an 'ea'
- Or None on failure
"""
pass
#</pydoc>
*/
static PyObject *dbg_get_thread_sreg_base(PyObject *py_tid, PyObject *py_sreg_value)
{
if ( !dbg_can_query() || !PyInt_Check(py_tid) || !PyInt_Check(py_sreg_value) )
Py_RETURN_NONE;
ea_t answer;
thid_t tid = PyInt_AsLong(py_tid);
int sreg_value = PyInt_AsLong(py_sreg_value);
if ( dbg->thread_get_sreg_base(tid, sreg_value, &answer) != 1 )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, pyul_t(answer));
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def dbg_read_memory(ea, sz):
"""
Reads from the debugee's memory at the specified ea
@return:
- The read buffer (as a string)
- Or None on failure
"""
pass
#</pydoc>
*/
static PyObject *dbg_read_memory(PyObject *py_ea, PyObject *py_sz)
{
uint64 ea, sz;
if ( !dbg_can_query() || !PyGetNumber(py_ea, &ea) || !PyGetNumber(py_sz, &sz) )
Py_RETURN_NONE;
// Create a Python string
PyObject *ret = PyString_FromStringAndSize(NULL, Py_ssize_t(sz));
if ( ret == NULL )
Py_RETURN_NONE;
// Get the internal buffer
Py_ssize_t len;
char *buf;
PyString_AsStringAndSize(ret, &buf, &len);
if ( (size_t)dbg->read_memory(ea_t(ea), buf, size_t(sz)) != sz )
{
// Release the string on failure
Py_DECREF(ret);
// Return None on failure
Py_RETURN_NONE;
}
return ret;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def dbg_write_memory(ea, buffer):
"""
Writes a buffer to the debugee's memory
@return: Boolean
"""
pass
#</pydoc>
*/
static PyObject *dbg_write_memory(PyObject *py_ea, PyObject *py_buf)
{
uint64 ea;
if ( !dbg_can_query() || !PyString_Check(py_buf) || !PyGetNumber(py_ea, &ea) )
Py_RETURN_NONE;
size_t sz = PyString_GET_SIZE(py_buf);
void *buf = (void *)PyString_AS_STRING(py_buf);
if ( dbg->write_memory(ea_t(ea), buf, sz) != sz )
Py_RETURN_FALSE;
Py_RETURN_TRUE;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def dbg_get_name():
"""
This function returns the current debugger's name.
@return: Debugger name or None if no debugger is active
"""
pass
#</pydoc>
*/
static PyObject *dbg_get_name() static PyObject *dbg_get_name()
{ {
if ( dbg == NULL ) if ( dbg == NULL )
@ -305,6 +350,47 @@ static PyObject *dbg_get_name()
return PyString_FromString(dbg->name); return PyString_FromString(dbg->name);
} }
//-------------------------------------------------------------------------
/*
#<pydoc>
def dbg_get_memory_info():
"""
This function returns the memory configuration of a debugged process.
@return:
None if no debugger is active
tuple(startEA, endEA, name, sclass, sbase, bitness, perm)
"""
pass
#</pydoc>
*/
static PyObject *dbg_get_memory_info()
{
if ( !dbg_can_query() )
Py_RETURN_NONE;
// Invalidate memory
invalidate_dbgmem_config();
invalidate_dbgmem_contents(BADADDR, BADADDR);
meminfo_vec_t areas;
dbg->get_memory_info(areas);
return meminfo_vec_t_to_py(areas);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def dbg_can_query():
"""
This function can be used to check if the debugger can be queried:
- debugger is loaded
- process is suspended
- process is not suspended but can take requests
@return: Boolean
"""
pass
#</pydoc>
*/
static bool dbg_can_query(); static bool dbg_can_query();
PyObject *py_appcall( PyObject *py_appcall(
ea_t func_ea, ea_t func_ea,
@ -368,15 +454,16 @@ bool can_exc_continue(const debug_event_t* ev)
import types import types
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# This class is used with |Appcall.array() method
class Appcall_array__(object): class Appcall_array__(object):
"""This class is used with Appcall.array() method"""
def __init__(self, tp): def __init__(self, tp):
self.__type = tp self.__type = tp
def pack(self, L): def pack(self, L):
"""Packs a list or tuple into a byref buffer"""
t = type(L) t = type(L)
if not (t == types.ListType or t == types.TupleType): if not (t == types.ListType or t == types.TupleType):
raise ValueError, "Either a list or a type must be passed" raise ValueError, "Either a list or a tuple must be passed"
self.__size = len(L) self.__size = len(L)
if self.__size == 1: if self.__size == 1:
self.__typedobj = Appcall__.typedobj(self.__type + ";") self.__typedobj = Appcall__.typedobj(self.__type + ";")
@ -390,6 +477,7 @@ class Appcall_array__(object):
return None return None
def try_to_convert_to_list(self, obj): def try_to_convert_to_list(self, obj):
"""Is this object a list? We check for the existance of attribute zero and attribute self.size-1"""
if not (hasattr(obj, "0") and hasattr(obj, str(self.__size-1))): if not (hasattr(obj, "0") and hasattr(obj, str(self.__size-1))):
return obj return obj
# at this point, we are sure we have an "idc list" # at this point, we are sure we have an "idc list"
@ -397,6 +485,7 @@ class Appcall_array__(object):
return [getattr(obj, str(x)) for x in xrange(0, self.__size)] return [getattr(obj, str(x)) for x in xrange(0, self.__size)]
def unpack(self, buf, as_list=True): def unpack(self, buf, as_list=True):
"""Unpacks an array back into a list or an object"""
# take the value from the special ref object # take the value from the special ref object
if isinstance(buf, PyIdc_cvt_refclass__): if isinstance(buf, PyIdc_cvt_refclass__):
buf = buf.value buf = buf.value
@ -412,15 +501,6 @@ class Appcall_array__(object):
return obj return obj
return self.try_to_convert_to_list(obj) return self.try_to_convert_to_list(obj)
# -----------------------------------------------------------------------
# This class is used with the obj() method
class Appcall_object__(object):
"""Helper class used to initialize empty objects"""
def __init__(self, **kwds):
self.__dict__ = kwds
def __getitem__(self, idx):
return getattr(self, idx)
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# Wrapper class for the appcall() # Wrapper class for the appcall()
@ -444,13 +524,29 @@ class Appcall_callable__(object):
self.__type = tp self.__type = tp
self.__fields = fld self.__fields = fld
self.__options = None # Appcall options self.__options = None # Appcall options
self.__timeout = None # Appcall timeout
def __get_timeout(self):
return self.__timeout
def __set_timeout(self, v):
self.__timeout = v
timeout = property(__get_timeout, __set_timeout)
"""An Appcall instance can change its timeout value with this attribute"""
def __get_options(self): def __get_options(self):
return self.__options if self.__options != None else Appcall__.get_appcall_options() return self.__options if self.__options != None else Appcall__.get_appcall_options()
def __set_options(self, v): def __set_options(self, v):
if self.timeout:
# If timeout value is set, then put the timeout flag and encode the timeout value
v |= Appcall__.APPCALL_TIMEOUT | (self.timeout << 16)
else:
# Timeout is not set, then clear the timeout flag
v &= ~Appcall__.APPCALL_TIMEOUT
self.__options = v self.__options = v
"""Sets the Appcall options locally to this Appcall instance"""
options = property(__get_options, __set_options) options = property(__get_options, __set_options)
"""Sets the Appcall options locally to this Appcall instance"""
def __call__(self, *args): def __call__(self, *args):
"""Make object callable. We redirect execution to idaapi.appcall()""" """Make object callable. We redirect execution to idaapi.appcall()"""
@ -475,7 +571,7 @@ class Appcall_callable__(object):
arg_list) arg_list)
except Exception, e: except Exception, e:
e_obj = e e_obj = e
# Restore appcall options # Restore appcall options
Appcall__.set_appcall_options(old_opt) Appcall__.set_appcall_options(old_opt)
@ -488,8 +584,9 @@ class Appcall_callable__(object):
return self.__ea return self.__ea
def __set_ea(self, val): def __set_ea(self, val):
self.__ea = val self.__ea = val
"""Returns or sets the EA associated with this object"""
ea = property(__get_ea, __set_ea) ea = property(__get_ea, __set_ea)
"""Returns or sets the EA associated with this object"""
def __get_size(self): def __get_size(self):
if self.__type == None: if self.__type == None:
@ -498,18 +595,20 @@ class Appcall_callable__(object):
if not r: if not r:
return -1 return -1
return r return r
"""Returns the size of the type"""
size = property(__get_size) size = property(__get_size)
"""Returns the size of the type"""
def __get_type(self): def __get_type(self):
return self.__type return self.__type
"""Returns the typestring"""
type = property(__get_type) type = property(__get_type)
"""Returns the typestring"""
def __get_fields(self): def __get_fields(self):
return self.__fields return self.__fields
"""Returns the typestring"""
fields = property(__get_fields) fields = property(__get_fields)
"""Returns the field names"""
def retrieve(self, src=None, flags=0): def retrieve(self, src=None, flags=0):
""" """
@ -531,8 +630,9 @@ class Appcall_callable__(object):
""" """
Packs an object into a given ea if provided or into a string if no address was passed. Packs an object into a given ea if provided or into a string if no address was passed.
@return: - If packing to a string then a Tuple(Boolean, packed_string or error code) @return:
- If packing to the database then a return code is returned (0 is success) - If packing to a string then a Tuple(Boolean, packed_string or error code)
- If packing to the database then a return code is returned (0 is success)
""" """
# no ea passed? thus pack to a string # no ea passed? thus pack to a string
@ -543,6 +643,8 @@ class Appcall_callable__(object):
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
class Appcall_consts__(object): class Appcall_consts__(object):
"""Helper class used by Appcall.Consts attribute
It is used to retrieve constants via attribute access"""
def __init__(self, default=0): def __init__(self, default=0):
self.__default = default self.__default = default
@ -551,26 +653,34 @@ class Appcall_consts__(object):
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
class Appcall__(object): class Appcall__(object):
APPCALL_MANUAL = 0x1
""" """
Only set up the appcall, do not run it. Only set up the appcall, do not run it.
you should call CleanupAppcall() when finished you should call CleanupAppcall() when finished
""" """
APPCALL_MANUAL = 0x1
APPCALL_DEBEV = 0x2
""" """
Return debug event information Return debug event information
If this bit is set, exceptions during appcall If this bit is set, exceptions during appcall
will generate idc exceptions with full will generate idc exceptions with full
information about the exception information about the exception
""" """
APPCALL_DEBEV = 0x2
APPCALL_TIMEOUT = 0x4
"""
Appcall with timeout
The timeout value in milliseconds is specified
in the high 2 bytes of the 'options' argument:
If timed out, errbuf will contain "timeout".
"""
def __init__(self): def __init__(self):
self.__consts = Appcall_consts__() self.__consts = Appcall_consts__()
def __get_consts(self): def __get_consts(self):
return self.__consts return self.__consts
"""Use Appcall.Consts.CONST_NAME to access constants"""
Consts = property(__get_consts) Consts = property(__get_consts)
"""Use Appcall.Consts.CONST_NAME to access constants"""
@staticmethod @staticmethod
def __name_or_ea(name_or_ea): def __name_or_ea(name_or_ea):
@ -591,7 +701,7 @@ class Appcall__(object):
@staticmethod @staticmethod
def proto(name_or_ea, prototype, flags = None): def proto(name_or_ea, prototype, flags = None):
"""Allows you to instantiate an appcall with the desired prototype""" """Allows you to instantiate an appcall (callable object) with the desired prototype"""
# resolve and raise exception on error # resolve and raise exception on error
ea = Appcall__.__name_or_ea(name_or_ea) ea = Appcall__.__name_or_ea(name_or_ea)
@ -605,7 +715,7 @@ class Appcall__(object):
return Appcall_callable__(ea, result[1], result[2]) return Appcall_callable__(ea, result[1], result[2])
def __getattr__(self, name_or_ea): def __getattr__(self, name_or_ea):
"""Allows you to call functions as if they were member functions""" """Allows you to call functions as if they were member functions (by returning a callable object)"""
# resolve and raise exception on error # resolve and raise exception on error
ea = self.__name_or_ea(name_or_ea) ea = self.__name_or_ea(name_or_ea)
if ea == _idaapi.BADADDR: if ea == _idaapi.BADADDR:
@ -663,7 +773,7 @@ class Appcall__(object):
@staticmethod @staticmethod
def obj(**kwds): def obj(**kwds):
"""Returns an empty object or objects with attributes as passed via its keywords arguments""" """Returns an empty object or objects with attributes as passed via its keywords arguments"""
return Appcall_object__(**kwds) return object_t(**kwds)
@staticmethod @staticmethod
def cstr(val): def cstr(val):
@ -695,12 +805,14 @@ class Appcall__(object):
@staticmethod @staticmethod
def set_appcall_options(opt): def set_appcall_options(opt):
"""Method to change the Appcall options globally (not per Appcall)"""
old_opt = Appcall__.get_appcall_options() old_opt = Appcall__.get_appcall_options()
_idaapi.cvar.inf.appcall_options = opt _idaapi.cvar.inf.appcall_options = opt
return old_opt return old_opt
@staticmethod @staticmethod
def get_appcall_options(): def get_appcall_options():
"""Return the global Appcall options"""
return _idaapi.cvar.inf.appcall_options return _idaapi.cvar.inf.appcall_options
@staticmethod @staticmethod

View File

@ -1,339 +1,612 @@
// Ignore the following symbols // Ignore the following symbols
%ignore WorkReg; %ignore WorkReg;
%ignore AbstractRegister; %ignore AbstractRegister;
%ignore rginfo; %ignore rginfo;
%ignore insn_t::get_canon_mnem; %ignore insn_t::get_canon_mnem;
%ignore insn_t::get_canon_feature; %ignore insn_t::get_canon_feature;
%ignore insn_t::is_canon_insn; %ignore insn_t::is_canon_insn;
%ignore bytes_t; %ignore bytes_t;
%ignore IDPOPT_STR; %ignore IDPOPT_STR;
%ignore IDPOPT_NUM; %ignore IDPOPT_NUM;
%ignore IDPOPT_BIT; %ignore IDPOPT_BIT;
%ignore IDPOPT_FLT; %ignore IDPOPT_FLT;
%ignore IDPOPT_I64; %ignore IDPOPT_I64;
%ignore IDPOPT_OK; %ignore IDPOPT_OK;
%ignore IDPOPT_BADKEY; %ignore IDPOPT_BADKEY;
%ignore IDPOPT_BADTYPE; %ignore IDPOPT_BADTYPE;
%ignore IDPOPT_BADVALUE; %ignore IDPOPT_BADVALUE;
%ignore set_options_t; %ignore set_options_t;
%ignore read_user_config_file; %ignore read_user_config_file;
%ignore s_preline; %ignore s_preline;
%ignore ca_operation_t; %ignore ca_operation_t;
%ignore _chkarg_cmd; %ignore _chkarg_cmd;
%ignore ENUM_SIZE; %ignore ENUM_SIZE;
%ignore asm_t::checkarg_dispatch; %ignore asm_t::checkarg_dispatch;
%ignore asm_t::func_header; %ignore asm_t::func_header;
%ignore asm_t::func_footer; %ignore asm_t::func_footer;
%ignore asm_t::get_type_name; %ignore asm_t::get_type_name;
%ignore instruc_t; %ignore instruc_t;
%ignore processor_t; %ignore processor_t;
%ignore ph; %ignore ph;
%ignore IDB_Callback; %ignore IDB_Callback;
%ignore IDP_Callback;
%ignore free_processor_module;
%ignore read_config_file; %ignore free_processor_module;
%ignore read_config_file;
%ignore gen_idb_event;
%ignore gen_idb_event;
%include "idp.hpp"
%include "idp.hpp"
%feature("director") IDB_Hooks; %feature("director") IDB_Hooks;
%feature("director") IDP_Hooks;
%inline %{ %inline %{
int idaapi IDB_Callback(void *ud, int notification_code, va_list va); int idaapi IDB_Callback(void *ud, int notification_code, va_list va);
class IDB_Hooks class IDB_Hooks
{ {
public: public:
virtual ~IDB_Hooks() {}; virtual ~IDB_Hooks() {};
bool hook() { return hook_to_notification_point(HT_IDB, IDB_Callback, this); } bool hook() { return hook_to_notification_point(HT_IDB, IDB_Callback, this); }
bool unhook() { return unhook_from_notification_point(HT_IDB, IDB_Callback, this); } bool unhook() { return unhook_from_notification_point(HT_IDB, IDB_Callback, this); }
/* Hook functions to override in Python */ /* Hook functions to override in Python */
virtual int byte_patched(ea_t ea) { return 0; }; virtual int byte_patched(ea_t ea) { return 0; };
virtual int cmt_changed(ea_t, bool repeatable_cmt) { return 0; }; virtual int cmt_changed(ea_t, bool repeatable_cmt) { return 0; };
virtual int ti_changed(ea_t ea, const type_t *type, const p_list *fnames) { msg("ti_changed hook not supported yet\n"); return 0; }; virtual int ti_changed(ea_t ea, const type_t *type, const p_list *fnames) { msg("ti_changed hook not supported yet\n"); return 0; };
virtual int op_ti_changed(ea_t ea, int n, const type_t *type, const p_list *fnames) { msg("op_ti_changed hook not supported yet\n"); return 0; }; virtual int op_ti_changed(ea_t ea, int n, const type_t *type, const p_list *fnames) { msg("op_ti_changed hook not supported yet\n"); return 0; };
virtual int op_type_changed(ea_t ea, int n) { return 0; }; virtual int op_type_changed(ea_t ea, int n) { return 0; };
virtual int enum_created(enum_t id) { return 0; }; virtual int enum_created(enum_t id) { return 0; };
virtual int enum_deleted(enum_t id) { return 0; }; virtual int enum_deleted(enum_t id) { return 0; };
virtual int enum_bf_changed(enum_t id) { return 0; }; virtual int enum_bf_changed(enum_t id) { return 0; };
virtual int enum_renamed(enum_t id) { return 0; }; virtual int enum_renamed(enum_t id) { return 0; };
virtual int enum_cmt_changed(enum_t id) { return 0; }; virtual int enum_cmt_changed(enum_t id) { return 0; };
virtual int enum_const_created(enum_t id, const_t cid) { return 0; }; virtual int enum_member_created(enum_t id, const_t cid) { return 0; };
virtual int enum_const_deleted(enum_t id, const_t cid) { return 0; }; virtual int enum_member_deleted(enum_t id, const_t cid) { return 0; };
virtual int struc_created(tid_t struc_id) { return 0; }; virtual int struc_created(tid_t struc_id) { return 0; };
virtual int struc_deleted(tid_t struc_id) { return 0; }; virtual int struc_deleted(tid_t struc_id) { return 0; };
virtual int struc_renamed(struc_t *sptr) { return 0; }; virtual int struc_renamed(struc_t *sptr) { return 0; };
virtual int struc_expanded(struc_t *sptr) { return 0; }; virtual int struc_expanded(struc_t *sptr) { return 0; };
virtual int struc_cmt_changed(tid_t struc_id) { return 0; }; virtual int struc_cmt_changed(tid_t struc_id) { return 0; };
virtual int struc_member_created(struc_t *sptr, member_t *mptr) { return 0; }; virtual int struc_member_created(struc_t *sptr, member_t *mptr) { return 0; };
virtual int struc_member_deleted(struc_t *sptr, tid_t member_id) { return 0; }; virtual int struc_member_deleted(struc_t *sptr, tid_t member_id) { return 0; };
virtual int struc_member_renamed(struc_t *sptr, member_t *mptr) { return 0; }; virtual int struc_member_renamed(struc_t *sptr, member_t *mptr) { return 0; };
virtual int struc_member_changed(struc_t *sptr, member_t *mptr) { return 0; }; virtual int struc_member_changed(struc_t *sptr, member_t *mptr) { return 0; };
virtual int thunk_func_created(func_t *pfn) { return 0; }; virtual int thunk_func_created(func_t *pfn) { return 0; };
virtual int func_tail_appended(func_t *pfn, func_t *tail) { return 0; }; virtual int func_tail_appended(func_t *pfn, func_t *tail) { return 0; };
virtual int func_tail_removed(func_t *pfn, ea_t tail_ea) { return 0; }; virtual int func_tail_removed(func_t *pfn, ea_t tail_ea) { return 0; };
virtual int tail_owner_changed(func_t *tail, ea_t owner_func) { return 0; }; virtual int tail_owner_changed(func_t *tail, ea_t owner_func) { return 0; };
virtual int func_noret_changed(func_t *pfn) { return 0; }; virtual int func_noret_changed(func_t *pfn) { return 0; };
virtual int segm_added(segment_t *s) { return 0; }; virtual int segm_added(segment_t *s) { return 0; };
virtual int segm_deleted(ea_t startEA) { return 0; }; virtual int segm_deleted(ea_t startEA) { return 0; };
virtual int segm_start_changed(segment_t *s) { return 0; }; virtual int segm_start_changed(segment_t *s) { return 0; };
virtual int segm_end_changed(segment_t *s) { return 0; }; virtual int segm_end_changed(segment_t *s) { return 0; };
virtual int segm_moved(ea_t from, ea_t to, asize_t size) { return 0; }; virtual int segm_moved(ea_t from, ea_t to, asize_t size) { return 0; };
}; };
int idaapi IDB_Callback(void *ud, int notification_code, va_list va) // Assemble an instruction into the database (display a warning if an error is found)
{ // args:
class IDB_Hooks *proxy = (class IDB_Hooks *)ud; // ea_t ea - linear address of instruction
ea_t ea, ea2; // ea_t cs - cs of instruction
bool repeatable_cmt; // ea_t ip - ip of instruction
/*type_t *type;*/ // bool use32 - is 32bit segment?
/* p_list *fnames; */ // const char *line - line to assemble
int n; // returns: 1: success, 0: failure
enum_t id; inline const int assemble(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
const_t cid; {
tid_t struc_id; int inslen;
struc_t *sptr; char buf[MAXSTR];
member_t *mptr;
tid_t member_id; if (ph.notify != NULL)
func_t *pfn; {
func_t *tail; inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf);
segment_t *seg; if (inslen > 0)
asize_t size; {
patch_many_bytes(ea, buf, inslen);
try { return 1;
switch (notification_code) }
{ }
case idb_event::byte_patched: return 0;
ea = va_arg(va, ea_t); }
return proxy->byte_patched(ea);
//<inline(py_idp)>
case idb_event::cmt_changed: //-------------------------------------------------------------------------
ea = va_arg(va, ea_t);
repeatable_cmt = va_arg(va, int); //-------------------------------------------------------------------------
return proxy->cmt_changed(ea, repeatable_cmt); /*
#if 0 #<pydoc>
case idb_event::ti_changed: def AssembleLine(ea, cs, ip, use32, line):
ea = va_arg(va, ea_t); """
type = va_arg(va, type_t *); Assemble an instruction to a buffer (display a warning if an error is found)
fnames = va_arg(va, fnames);
return proxy->ti_changed(ea, type, fnames); @param ea: linear address of instruction
@param cs: cs of instruction
case idb_event::op_ti_changed: @param ip: ip of instruction
ea = va_arg(va, ea_t); @param use32: is 32bit segment
n = va_arg(va, int); @param line: line to assemble
type = va_arg(va, type_t *); @return:
fnames = va_arg(va, fnames); - None on failure
return proxy->op_ti_changed(ea, n, type, fnames); - or a string containing the assembled instruction
#endif """
case idb_event::op_type_changed: pass
ea = va_arg(va, ea_t); #</pydoc>
n = va_arg(va, int); */
return proxy->op_type_changed(ea, n); static PyObject *AssembleLine(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
{
case idb_event::enum_created: int inslen;
id = va_arg(va, enum_t); char buf[MAXSTR];
return proxy->enum_created(id); if (ph.notify != NULL &&
(inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0)
case idb_event::enum_deleted: {
id = va_arg(va, enum_t); return PyString_FromStringAndSize(buf, inslen);
return proxy->enum_deleted(id); }
Py_RETURN_NONE;
case idb_event::enum_bf_changed: }
id = va_arg(va, enum_t);
return proxy->enum_bf_changed(id); //-------------------------------------------------------------------------
/*
case idb_event::enum_cmt_changed: #<pydoc>
id = va_arg(va, enum_t); def ph_get_tbyte_size():
return proxy->enum_cmt_changed(id); """
Returns the 'ph.tbyte_size' field as defined in he processor module
case idb_event::enum_const_created: """
id = va_arg(va, enum_t); pass
cid = va_arg(va, const_t); #</pydoc>
return proxy->enum_const_created(id, cid); */
static size_t ph_get_tbyte_size()
case idb_event::enum_const_deleted: {
id = va_arg(va, enum_t); return ph.tbyte_size;
cid = va_arg(va, const_t); }
return proxy->enum_const_deleted(id, cid);
//-------------------------------------------------------------------------
case idb_event::struc_created: /*
struc_id = va_arg(va, tid_t); #<pydoc>
return proxy->struc_created(struc_id); def ph_get_id():
"""
case idb_event::struc_deleted: Returns the 'ph.id' field
struc_id = va_arg(va, tid_t); """
return proxy->struc_deleted(struc_id); pass
#</pydoc>
case idb_event::struc_renamed: */
sptr = va_arg(va, struc_t *); static size_t ph_get_id()
return proxy->struc_renamed(sptr); {
return ph.id;
case idb_event::struc_expanded: }
sptr = va_arg(va, struc_t *);
return proxy->struc_expanded(sptr); //-------------------------------------------------------------------------
/*
case idb_event::struc_cmt_changed: #<pydoc>
struc_id = va_arg(va, tid_t); def ph_get_instruc():
return proxy->struc_cmt_changed(struc_id); """
Returns a list of tuples (instruction_name, instruction_feature) containing the
case idb_event::struc_member_created: instructions list as defined in he processor module
sptr = va_arg(va, struc_t *); """
mptr = va_arg(va, member_t *); pass
return proxy->struc_member_created(sptr, mptr); #</pydoc>
*/
case idb_event::struc_member_deleted: static PyObject *ph_get_instruc()
sptr = va_arg(va, struc_t *); {
member_id = va_arg(va, tid_t); Py_ssize_t i = 0;
return proxy->struc_member_deleted(sptr, member_id); PyObject *py_result = PyTuple_New(ph.instruc_end - ph.instruc_start);
for ( instruc_t *p = ph.instruc + ph.instruc_start, *end = ph.instruc + ph.instruc_end;
case idb_event::struc_member_renamed: p != end;
sptr = va_arg(va, struc_t *); ++p )
mptr = va_arg(va, member_t *); {
return proxy->struc_member_renamed(sptr, mptr); PyTuple_SetItem(py_result, i++, Py_BuildValue("(sI)", p->name, p->feature));
}
case idb_event::struc_member_changed: return py_result;
sptr = va_arg(va, struc_t *); }
mptr = va_arg(va, member_t *);
return proxy->struc_member_changed(sptr, mptr); //-------------------------------------------------------------------------
/*
case idb_event::thunk_func_created: #<pydoc>
pfn = va_arg(va, func_t *); def ph_get_regnames():
return proxy->thunk_func_created(pfn); """
Returns the list of register names as defined in the processor module
case idb_event::func_tail_appended: """
pfn = va_arg(va, func_t *); pass
tail = va_arg(va, func_t *); #</pydoc>
return proxy->func_tail_appended(pfn, tail); */
static PyObject *ph_get_regnames()
case idb_event::func_tail_removed: {
pfn = va_arg(va, func_t *); Py_ssize_t i = 0;
ea = va_arg(va, ea_t); PyObject *py_result = PyList_New(ph.regsNum);
return proxy->func_tail_removed(pfn, ea); for ( Py_ssize_t i=0; i<ph.regsNum; i++ )
PyList_SetItem(py_result, i, PyString_FromString(ph.regNames[i]));
case idb_event::tail_owner_changed: return py_result;
tail = va_arg(va, func_t *); }
ea = va_arg(va, ea_t);
return proxy->tail_owner_changed(tail, ea); //-------------------------------------------------------------------------
/*
case idb_event::func_noret_changed: #<pydoc>
pfn = va_arg(va, func_t *); class IDP_Hooks(object):
return proxy->func_noret_changed(pfn); def custom_ana(self):
"""
case idb_event::segm_added: Analyzes and decodes an instruction at idaapi.cmd.ea
seg = va_arg(va, segment_t *); - cmd.itype must be set >= idaapi.CUSTOM_CMD_ITYPE
return proxy->segm_added(seg); - cmd.size must be set to the instruction length
case idb_event::segm_deleted: @return: Boolean
ea = va_arg(va, ea_t); - False if the instruction is not recognized
return proxy->segm_deleted(ea); - True if the instruction was decoded. idaapi.cmd should be filled in that case.
"""
case idb_event::segm_start_changed: pass
seg = va_arg(va, segment_t *);
return proxy->segm_start_changed(seg); def custom_out(self):
"""
case idb_event::segm_end_changed: Outputs the instruction defined in idaapi.cmd
seg = va_arg(va, segment_t *);
return proxy->segm_end_changed(seg); @return: Boolean (whether this instruction can be outputted or not)
"""
case idb_event::segm_moved: pass
ea = va_arg(va, ea_t);
ea2 = va_arg(va, ea_t); def custom_emu(self):
size = va_arg(va, asize_t); """
return proxy->segm_moved(ea, ea2, size); Emulate instruction, create cross-references, plan to analyze
} subsequent instructions, modify flags etc. Upon entrance to this function
} all information about the instruction is in 'cmd' structure.
catch (Swig::DirectorException &)
{ @return: Boolean (whether this instruction has been emulated or not)
msg("Exception in IDP Hook function:\n"); """
if (PyErr_Occurred()) pass
{
PyErr_Print(); def custom_outop(self, op):
} """
} Notification to generate operand text.
return 0; If False was returned, then the standard operand output function will be called.
}
The output buffer is inited with init_output_buffer()
// Assemble an instruction into the database (display a warning if an error is found) and this notification may use out_...() functions to form the operand text
// args:
// ea_t ea - linear address of instruction @return: Boolean (whether the operand has been outputted or not)
// ea_t cs - cs of instruction """
// ea_t ip - ip of instruction
// bool use32 - is 32bit segment? def custom_mnem(self):
// const char *line - line to assemble """
// returns: 1: success, 0: failure Prints the mnemonic of the instruction defined in idaapi.cmd
inline const int assemble(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
{ @return:
int inslen; - None: No mnemonic. IDA will use the default mnemonic value if present
char buf[MAXSTR]; - String: The desired mnemonic string
"""
if (ph.notify != NULL)
{ def is_sane_insn(self, no_crefs):
inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf); """
if (inslen > 0) is the instruction sane for the current file type?
{ @param no_crefs:
patch_many_bytes(ea, buf, inslen); - 1: the instruction has no code refs to it.
return 1; ida just tries to convert unexplored bytes
} to an instruction (but there is no other
} reason to convert them into an instruction)
return 0; - 0: the instruction is created because
} of some coderef, user request or another
weighty reason.
//<inline(py_idp)> @return: 1-ok, <=0-no, the instruction isn't likely to appear in the program
//------------------------------------------------------------------------- """
pass
//-------------------------------------------------------------------------
// Assemble an instruction to a buffer (display a warning if an error is found) def is_sane_insn(self, no_crefs):
// args: """
// ea_t ea - linear address of instruction can a function start here?
// ea_t cs - cs of instruction @param state: autoanalysis phase
// ea_t ip - ip of instruction 0: creating functions
// bool use32 - is 32bit segment? 1: creating chunks
// const char *line - line to assemble
// returns: 1: success, 0: failure @return: integer (probability 0..100)
static PyObject *AssembleLine(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line) """
{ pass
int inslen; #</pydoc>
char buf[MAXSTR]; */
if (ph.notify != NULL && int idaapi IDP_Callback(void *ud, int notification_code, va_list va);
(inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0) class IDP_Hooks
{ {
return PyString_FromStringAndSize(buf, inslen); public:
} virtual ~IDP_Hooks()
Py_RETURN_NONE; {
} }
//------------------------------------------------------------------------- bool hook()
static size_t ph_get_tbyte_size() {
{ return hook_to_notification_point(HT_IDP, IDP_Callback, this);
return ph.tbyte_size; }
}
bool unhook()
//------------------------------------------------------------------------- {
static PyObject *ph_get_instruc() return unhook_from_notification_point(HT_IDP, IDP_Callback, this);
{ }
Py_ssize_t i = 0;
PyObject *py_result = PyTuple_New(ph.instruc_end - ph.instruc_start); virtual bool custom_ana()
for ( instruc_t *p = ph.instruc + ph.instruc_start, *end = ph.instruc + ph.instruc_end; {
p != end; return false;
++p ) }
{
PyTuple_SetItem(py_result, i++, Py_BuildValue("(sI)", p->name, p->feature)); virtual bool custom_out()
} {
return py_result; return false;
} }
//------------------------------------------------------------------------- virtual bool custom_emu()
static PyObject *ph_get_regnames() {
{ return false;
Py_ssize_t i = 0; }
PyObject *py_result = PyList_New(ph.regsNum);
for ( Py_ssize_t i=0; i<ph.regsNum; i++ ) virtual bool custom_outop(PyObject *py_op)
PyList_SetItem(py_result, i, PyString_FromString(ph.regNames[i])); {
return py_result; return false;
} }
//</inline(py_idp)> virtual PyObject *custom_mnem()
%} {
return NULL;
}
virtual int is_sane_insn(int no_crefs)
{
return 0;
}
virtual int may_be_func(int state)
{
return 0;
}
};
//</inline(py_idp)>
%}
%{
int idaapi IDB_Callback(void *ud, int notification_code, va_list va)
{
class IDB_Hooks *proxy = (class IDB_Hooks *)ud;
ea_t ea, ea2;
bool repeatable_cmt;
/*type_t *type;*/
/* p_list *fnames; */
int n;
enum_t id;
const_t cid;
tid_t struc_id;
struc_t *sptr;
member_t *mptr;
tid_t member_id;
func_t *pfn;
func_t *tail;
segment_t *seg;
asize_t size;
try {
switch (notification_code)
{
case idb_event::byte_patched:
ea = va_arg(va, ea_t);
return proxy->byte_patched(ea);
case idb_event::cmt_changed:
ea = va_arg(va, ea_t);
repeatable_cmt = va_arg(va, int);
return proxy->cmt_changed(ea, repeatable_cmt);
#if 0
case idb_event::ti_changed:
ea = va_arg(va, ea_t);
type = va_arg(va, type_t *);
fnames = va_arg(va, fnames);
return proxy->ti_changed(ea, type, fnames);
case idb_event::op_ti_changed:
ea = va_arg(va, ea_t);
n = va_arg(va, int);
type = va_arg(va, type_t *);
fnames = va_arg(va, fnames);
return proxy->op_ti_changed(ea, n, type, fnames);
#endif
case idb_event::op_type_changed:
ea = va_arg(va, ea_t);
n = va_arg(va, int);
return proxy->op_type_changed(ea, n);
case idb_event::enum_created:
id = va_arg(va, enum_t);
return proxy->enum_created(id);
case idb_event::enum_deleted:
id = va_arg(va, enum_t);
return proxy->enum_deleted(id);
case idb_event::enum_bf_changed:
id = va_arg(va, enum_t);
return proxy->enum_bf_changed(id);
case idb_event::enum_cmt_changed:
id = va_arg(va, enum_t);
return proxy->enum_cmt_changed(id);
case idb_event::enum_member_created:
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_member_created(id, cid);
case idb_event::enum_member_deleted:
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_member_deleted(id, cid);
case idb_event::struc_created:
struc_id = va_arg(va, tid_t);
return proxy->struc_created(struc_id);
case idb_event::struc_deleted:
struc_id = va_arg(va, tid_t);
return proxy->struc_deleted(struc_id);
case idb_event::struc_renamed:
sptr = va_arg(va, struc_t *);
return proxy->struc_renamed(sptr);
case idb_event::struc_expanded:
sptr = va_arg(va, struc_t *);
return proxy->struc_expanded(sptr);
case idb_event::struc_cmt_changed:
struc_id = va_arg(va, tid_t);
return proxy->struc_cmt_changed(struc_id);
case idb_event::struc_member_created:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_created(sptr, mptr);
case idb_event::struc_member_deleted:
sptr = va_arg(va, struc_t *);
member_id = va_arg(va, tid_t);
return proxy->struc_member_deleted(sptr, member_id);
case idb_event::struc_member_renamed:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_renamed(sptr, mptr);
case idb_event::struc_member_changed:
sptr = va_arg(va, struc_t *);
mptr = va_arg(va, member_t *);
return proxy->struc_member_changed(sptr, mptr);
case idb_event::thunk_func_created:
pfn = va_arg(va, func_t *);
return proxy->thunk_func_created(pfn);
case idb_event::func_tail_appended:
pfn = va_arg(va, func_t *);
tail = va_arg(va, func_t *);
return proxy->func_tail_appended(pfn, tail);
case idb_event::func_tail_removed:
pfn = va_arg(va, func_t *);
ea = va_arg(va, ea_t);
return proxy->func_tail_removed(pfn, ea);
case idb_event::tail_owner_changed:
tail = va_arg(va, func_t *);
ea = va_arg(va, ea_t);
return proxy->tail_owner_changed(tail, ea);
case idb_event::func_noret_changed:
pfn = va_arg(va, func_t *);
return proxy->func_noret_changed(pfn);
case idb_event::segm_added:
seg = va_arg(va, segment_t *);
return proxy->segm_added(seg);
case idb_event::segm_deleted:
ea = va_arg(va, ea_t);
return proxy->segm_deleted(ea);
case idb_event::segm_start_changed:
seg = va_arg(va, segment_t *);
return proxy->segm_start_changed(seg);
case idb_event::segm_end_changed:
seg = va_arg(va, segment_t *);
return proxy->segm_end_changed(seg);
case idb_event::segm_moved:
ea = va_arg(va, ea_t);
ea2 = va_arg(va, ea_t);
size = va_arg(va, asize_t);
return proxy->segm_moved(ea, ea2, size);
}
}
catch (Swig::DirectorException &)
{
msg("Exception in IDP Hook function:\n");
if (PyErr_Occurred())
{
PyErr_Print();
}
}
return 0;
}
//<code(py_idp)>
//-------------------------------------------------------------------------
int idaapi IDP_Callback(void *ud, int notification_code, va_list va)
{
IDP_Hooks *proxy = (IDP_Hooks *)ud;
int ret;
try
{
switch ( notification_code )
{
default:
ret = 0;
break;
case processor_t::custom_ana:
ret = proxy->custom_ana() ? 1 + cmd.size : 0;
break;
case processor_t::custom_out:
ret = proxy->custom_out() ? 2 : 0;
break;
case processor_t::custom_emu:
ret = proxy->custom_emu() ? 2 : 0;
break;
case processor_t::custom_outop:
{
op_t *op = va_arg(va, op_t *);
PyObject *py_obj = create_idaapi_linked_class_instance(S_PY_OP_T_CLSNAME, op);
if ( py_obj == NULL )
break;
ret = proxy->custom_outop(py_obj) ? 2 : 0;
Py_XDECREF(py_obj);
break;
}
case processor_t::custom_mnem:
{
PyObject *py_ret = proxy->custom_mnem();
if ( py_ret != NULL && PyString_Check(py_ret) )
{
char *outbuffer = va_arg(va, char *);
size_t bufsize = va_arg(va, size_t);
qstrncpy(outbuffer, PyString_AS_STRING(py_ret), bufsize);
ret = 2;
}
else
{
ret = 0;
}
Py_XDECREF(py_ret);
break;
}
case processor_t::is_sane_insn:
{
int no_crefs = va_arg(va, int);
ret = proxy->is_sane_insn(no_crefs);
break;
}
case processor_t::may_be_func:
{
int state = va_arg(va, int);
ret = proxy->may_be_func(state);
break;
}
}
}
catch (Swig::DirectorException &)
{
msg("Exception in IDP Hook function:\n");
if ( PyErr_Occurred() )
PyErr_Print();
}
return ret;
}
//-------------------------------------------------------------------------
//</code(py_idp)>
%}

File diff suppressed because it is too large Load Diff

View File

@ -1,186 +1,225 @@
// FIXME: These should be fixed // FIXME: These should be fixed
%ignore requires_color_esc; %ignore requires_color_esc;
%ignore tag_on; %ignore tag_on;
%ignore tag_remove; %ignore tag_remove;
%ignore tag_off; %ignore tag_off;
%ignore tag_addchr; %ignore tag_addchr;
%ignore tag_addstr; %ignore tag_addstr;
%ignore tag_addr; %ignore tag_addr;
%ignore tag_advance; %ignore tag_advance;
%ignore tag_skipcodes; %ignore tag_skipcodes;
%ignore tag_skipcode; %ignore tag_skipcode;
%ignore set_user_defined_prefix; %ignore set_user_defined_prefix;
%ignore get_user_defined_prefix; %ignore get_user_defined_prefix;
// Ignore va_list versions // Ignore va_list versions
%ignore printf_line_v; %ignore printf_line_v;
%ignore gen_colored_cmt_line_v; %ignore gen_colored_cmt_line_v;
%ignore gen_cmt_line_v; %ignore gen_cmt_line_v;
%ignore add_long_cmt_v; %ignore add_long_cmt_v;
%ignore describex; %ignore describex;
// Kernel-only and unexported symbols // Kernel-only and unexported symbols
%ignore init_sourcefiles; %ignore init_sourcefiles;
%ignore save_sourcefiles; %ignore save_sourcefiles;
%ignore term_sourcefiles; %ignore term_sourcefiles;
%ignore move_sourcefiles; %ignore move_sourcefiles;
%ignore gen_xref_lines; %ignore gen_xref_lines;
%ignore ml_getcmt_t; %ignore ml_getcmt_t;
%ignore ml_getnam_t; %ignore ml_getnam_t;
%ignore ml_genxrf_t; %ignore ml_genxrf_t;
%ignore ml_saver_t; %ignore ml_saver_t;
%ignore setup_makeline; %ignore setup_makeline;
%ignore MAKELINE_NONE; %ignore MAKELINE_NONE;
%ignore MAKELINE_BINPREF; %ignore MAKELINE_BINPREF;
%ignore MAKELINE_VOID; %ignore MAKELINE_VOID;
%ignore MAKELINE_STACK; %ignore MAKELINE_STACK;
%ignore save_line_in_array; %ignore save_line_in_array;
%ignore init_lines_array; %ignore init_lines_array;
%ignore finish_makeline; %ignore finish_makeline;
%ignore generate_disassembly; %ignore generate_disassembly;
%ignore gen_labeled_line; %ignore gen_labeled_line;
%ignore gen_lname_line; %ignore gen_lname_line;
%ignore makeline_producer_t; %ignore makeline_producer_t;
%ignore set_makeline_producer; %ignore set_makeline_producer;
%ignore closing_comment; %ignore closing_comment;
%ignore close_comment; %ignore close_comment;
%ignore copy_extra_lines; %ignore copy_extra_lines;
%ignore ExtraLines; %ignore ExtraLines;
%ignore ExtraKill; %ignore ExtraKill;
%ignore ExtraFree; %ignore ExtraFree;
%ignore Dumper; %ignore Dumper;
%ignore init_lines; %ignore init_lines;
%ignore save_lines; %ignore save_lines;
%ignore term_lines; %ignore term_lines;
%ignore gl_namedone; %ignore gl_namedone;
%ignore data_as_stack; %ignore data_as_stack;
%ignore calc_stack_alignment; %ignore calc_stack_alignment;
%ignore align_down_to_stack; %ignore align_down_to_stack;
%ignore align_up_to_stack; %ignore align_up_to_stack;
%ignore remove_spaces; %ignore remove_spaces;
%ignore bgcolors;
%include "lines.hpp"
%include "lines.hpp"
%rename (generate_disassembly) py_generate_disassembly;
%rename (tag_remove) py_tag_remove; %rename (generate_disassembly) py_generate_disassembly;
%rename (tag_addr) py_tag_addr; %rename (tag_remove) py_tag_remove;
%rename (tag_skipcodes) py_tag_skipcodes; %rename (tag_addr) py_tag_addr;
%rename (tag_skipcode) py_tag_skipcode; %rename (tag_skipcodes) py_tag_skipcodes;
%rename (tag_advance) py_tag_advance; %rename (tag_skipcode) py_tag_skipcode;
%rename (generate_disassembly) py_generate_disassembly; %rename (tag_advance) py_tag_advance;
%rename (generate_disassembly) py_generate_disassembly;
%inline
{ %inline %{
//<inline(py_lines)> //<inline(py_lines)>
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
PyObject *py_tag_remove(const char *instr) /*
{ #<pydoc>
size_t sz = strlen(instr); def tag_remove(colstr):
char *buf = new char[sz + 5]; """
if ( buf == NULL ) Remove color escape sequences from a string
Py_RETURN_NONE; @param colstr: the colored string with embedded tags
ssize_t r = tag_remove(instr, buf, sz); @return:
PyObject *res; None on failure
if ( r < 0 ) or a new string w/o the tags
{ """
Py_INCREF(Py_None); pass
res = Py_None; #</pydoc>
} */
else PyObject *py_tag_remove(const char *instr)
{ {
res = PyString_FromString(buf); size_t sz = strlen(instr);
} char *buf = new char[sz + 5];
delete [] buf; if ( buf == NULL )
return res; Py_RETURN_NONE;
} ssize_t r = tag_remove(instr, buf, sz);
PyObject *res;
//------------------------------------------------------------------------- if ( r < 0 )
PyObject *py_tag_addr(ea_t ea) {
{ Py_INCREF(Py_None);
char buf[100]; res = Py_None;
tag_addr(buf, buf + sizeof(buf), ea); }
return PyString_FromString(buf); else
} {
res = PyString_FromString(buf);
//------------------------------------------------------------------------- }
int py_tag_skipcode(const char *line) delete [] buf;
{ return res;
return tag_skipcode(line)-line; }
}
//-------------------------------------------------------------------------
//------------------------------------------------------------------------- PyObject *py_tag_addr(ea_t ea)
int py_tag_skipcodes(const char *line) {
{ char buf[100];
return tag_skipcodes(line)-line; tag_addr(buf, buf + sizeof(buf), ea);
} return PyString_FromString(buf);
}
//-------------------------------------------------------------------------
int py_tag_advance(const char *line, int cnt) //-------------------------------------------------------------------------
{ int py_tag_skipcode(const char *line)
return tag_advance(line, cnt)-line; {
} return tag_skipcode(line)-line;
}
//-------------------------------------------------------------------------
PyObject *py_generate_disassembly(ea_t ea, int max_lines, bool as_stack, bool notags) //-------------------------------------------------------------------------
{ int py_tag_skipcodes(const char *line)
if ( max_lines <= 0 ) {
Py_RETURN_NONE; return tag_skipcodes(line)-line;
}
qstring qbuf;
char **lines = new char *[max_lines]; //-------------------------------------------------------------------------
int lnnum; int py_tag_advance(const char *line, int cnt)
int nlines = generate_disassembly(ea, lines, max_lines, &lnnum, as_stack); {
return tag_advance(line, cnt)-line;
PyObject *py_tuple = PyTuple_New(nlines); }
for ( int i=0; i<nlines; i++ )
{ //-------------------------------------------------------------------------
const char *s = lines[i]; /*
size_t line_len = strlen(s); #<pydoc>
if ( notags ) def generate_disassembly(ea, max_lines, as_stack, notags):
{ """
qbuf.resize(line_len+5); Generate disassembly lines (many lines) and put them into a buffer
tag_remove(s, &qbuf[0], line_len);
s = (const char *)&qbuf[0]; @param ea: address to generate disassembly for
} @param max_lines: how many lines max to generate
PyTuple_SetItem(py_tuple, i, PyString_FromString(s)); @param as_stack: Display undefined items as 2/4/8 bytes
qfree(lines[i]); @return:
} - None on failure
delete [] lines; - tuple(most_important_line_number, tuple(lines)) : Returns a tuple containing
PyObject *py_result = Py_BuildValue("(iO)", lnnum, py_tuple); the most important line number and a tuple of generated lines
Py_DECREF(py_tuple); """
return py_result; pass
} #</pydoc>
//</inline(py_lines)> */
PyObject *py_generate_disassembly(
} ea_t ea,
int max_lines,
%pythoncode %{ bool as_stack,
#<pycode(py_lines)> bool notags)
{
# ---------------- Color escape sequence defitions ------------------------- if ( max_lines <= 0 )
COLOR_ADDR_SIZE = 16 if _idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL else 8 Py_RETURN_NONE;
SCOLOR_FG_MAX = '\x28' # Max color number
SCOLOR_OPND1 = chr(cvar.COLOR_ADDR+1) # Instruction operand 1 qstring qbuf;
SCOLOR_OPND2 = chr(cvar.COLOR_ADDR+2) # Instruction operand 2 char **lines = new char *[max_lines];
SCOLOR_OPND3 = chr(cvar.COLOR_ADDR+3) # Instruction operand 3 int lnnum;
SCOLOR_OPND4 = chr(cvar.COLOR_ADDR+4) # Instruction operand 4 int nlines = generate_disassembly(ea, lines, max_lines, &lnnum, as_stack);
SCOLOR_OPND5 = chr(cvar.COLOR_ADDR+5) # Instruction operand 5
SCOLOR_OPND6 = chr(cvar.COLOR_ADDR+6) # Instruction operand 6 PyObject *py_tuple = PyTuple_New(nlines);
SCOLOR_UTF8 = chr(cvar.COLOR_ADDR+10) # Following text is UTF-8 encoded for ( int i=0; i<nlines; i++ )
{
# ---------------- Line prefix colors -------------------------------------- const char *s = lines[i];
PALETTE_SIZE = (cvar.COLOR_FG_MAX+_idaapi.COLOR_BG_MAX) size_t line_len = strlen(s);
if ( notags )
def requires_color_esc(c): {
""" qbuf.resize(line_len+5);
Checks if the given character requires escaping tag_remove(s, &qbuf[0], line_len);
@param c: character (string of one char) s = (const char *)&qbuf[0];
@return: Boolean }
""" PyTuple_SetItem(py_tuple, i, PyString_FromString(s));
t = ord(c[0]) qfree(lines[i]);
return c >= COLOR_ON and c <= COLOR_INV }
delete [] lines;
def COLSTR(str,tag): PyObject *py_result = Py_BuildValue("(iO)", lnnum, py_tuple);
return SCOLOR_ON + tag + str + SCOLOR_OFF + tag Py_DECREF(py_tuple);
return py_result;
#</pycode(py_lines)> }
//</inline(py_lines)>
%}
%pythoncode %{
#<pycode(py_lines)>
# ---------------- Color escape sequence defitions -------------------------
COLOR_ADDR_SIZE = 16 if _idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL else 8
SCOLOR_FG_MAX = '\x28' # Max color number
SCOLOR_OPND1 = chr(cvar.COLOR_ADDR+1) # Instruction operand 1
SCOLOR_OPND2 = chr(cvar.COLOR_ADDR+2) # Instruction operand 2
SCOLOR_OPND3 = chr(cvar.COLOR_ADDR+3) # Instruction operand 3
SCOLOR_OPND4 = chr(cvar.COLOR_ADDR+4) # Instruction operand 4
SCOLOR_OPND5 = chr(cvar.COLOR_ADDR+5) # Instruction operand 5
SCOLOR_OPND6 = chr(cvar.COLOR_ADDR+6) # Instruction operand 6
SCOLOR_UTF8 = chr(cvar.COLOR_ADDR+10) # Following text is UTF-8 encoded
# ---------------- Line prefix colors --------------------------------------
PALETTE_SIZE = (cvar.COLOR_FG_MAX+_idaapi.COLOR_BG_MAX)
def requires_color_esc(c):
"""
Checks if the given character requires escaping
@param c: character (string of one char)
@return: Boolean
"""
t = ord(c[0])
return c >= COLOR_ON and c <= COLOR_INV
def COLSTR(str, tag):
"""
Utility function to create a colored line
@param str: The string
@param tag: Color tag constant. One of SCOLOR_XXXX
"""
return SCOLOR_ON + tag + str + SCOLOR_OFF + tag
#</pycode(py_lines)>
%} %}

View File

@ -72,12 +72,14 @@
%ignore save_fileregions; %ignore save_fileregions;
%ignore add_fileregion; %ignore add_fileregion;
%ignore move_fileregions; %ignore move_fileregions;
%ignore del_fileregions;
%ignore local_gen_idc_file; %ignore local_gen_idc_file;
%ignore print_all_places; %ignore print_all_places;
%ignore save_text_line; %ignore save_text_line;
%ignore print_all_structs; %ignore print_all_structs;
%ignore print_all_enums; %ignore print_all_enums;
%ignore enum_processor_modules; %ignore enum_processor_modules;
%ignore enum_plugins;
%ignore database_id0; %ignore database_id0;
%ignore is_database_ext; %ignore is_database_ext;
%ignore ida_database_memory; %ignore ida_database_memory;

View File

@ -45,13 +45,47 @@ static int idaapi py_import_enum_cb(
Py_XDECREF(py_result); Py_XDECREF(py_result);
return r; return r;
} }
//-------------------------------------------------------------------------
switch_info_ex_t *switch_info_ex_t_get_clink(PyObject *self)
{
if ( !PyObject_HasAttrString(self, S_CLINK_NAME) )
return NULL;
switch_info_ex_t *r;
PyObject *attr = PyObject_GetAttrString(self, S_CLINK_NAME);
if ( PyCObject_Check(attr) )
r = (switch_info_ex_t *) PyCObject_AsVoidPtr(attr);
else
r = NULL;
Py_DECREF(attr);
return r;
}
//</code(py_nalt)> //</code(py_nalt)>
%} %}
%rename (get_switch_info_ex) py_get_switch_info_ex;
%rename (set_switch_info_ex) py_set_switch_info_ex;
%rename (del_switch_info_ex) py_del_switch_info_ex;
%rename (create_switch_xrefs) py_create_switch_xrefs;
%rename (create_switch_table) py_create_switch_table;
%inline %{ %inline %{
//<inline(py_nalt)> //<inline(py_nalt)>
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
PyObject *py_get_import_module_name(int mod_index) /*
#<pydoc>
def get_import_module_name(path, fname, callback):
"""
Returns the name of an imported module given its index
@return: None or the module name
"""
pass
#</pydoc>
*/
static PyObject *py_get_import_module_name(int mod_index)
{ {
char buf[MAXSTR]; char buf[MAXSTR];
if ( !get_import_module_name(mod_index, buf, sizeof(buf)) ) if ( !get_import_module_name(mod_index, buf, sizeof(buf)) )
@ -60,14 +94,584 @@ PyObject *py_get_import_module_name(int mod_index)
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// enumerate imports from specific module /*
// return: 1-finished ok, -1 on error, otherwise callback return value (<=0) #<pydoc>
int py_enum_import_names(int mod_index, PyObject *py_cb) def get_switch_info_ex(ea):
"""
Returns the a switch_info_ex_t structure containing the information about the switch.
Please refer to the SDK sample 'uiswitch'
@return: None or switch_info_ex_t instance
"""
pass
#</pydoc>
*/
PyObject *py_get_switch_info_ex(ea_t ea)
{
switch_info_ex_t *ex = new switch_info_ex_t();
PyObject *py_obj;
if ( ::get_switch_info_ex(ea, ex, sizeof(switch_info_ex_t)) <= 0
|| (py_obj = create_idaapi_linked_class_instance(S_PY_SWIEX_CLSNAME, ex)) == NULL )
{
delete ex;
Py_RETURN_NONE;
}
return py_obj;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def create_switch_xrefs(insn_ea, si):
"""
This function creates xrefs from the indirect jump.
Usually there is no need to call this function directly because the kernel
will call it for switch tables
Note: Custom switch information are not supported yet.
@param insn_ea: address of the 'indirect jump' instruction
@param si: switch information
@return: Boolean
"""
pass
#</pydoc>
*/
idaman bool ida_export py_create_switch_xrefs(
ea_t insn_ea,
PyObject *py_swi)
{
switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi);
if ( swi == NULL )
return false;
create_switch_xrefs(insn_ea, swi);
return true;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def create_switch_table(insn_ea, si):
"""
Create switch table from the switch information
@param insn_ea: address of the 'indirect jump' instruction
@param si: switch information
@return: Boolean
"""
pass
#</pydoc>
*/
idaman bool ida_export py_create_switch_table(
ea_t insn_ea,
PyObject *py_swi)
{
switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi);
if ( swi == NULL )
return false;
create_switch_table(insn_ea, swi);
return true;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def set_switch_info_ex(ea, switch_info_ex):
"""
Saves the switch information in the database
Please refer to the SDK sample 'uiswitch'
@return: Boolean
"""
pass
#</pydoc>
*/
bool py_set_switch_info_ex(ea_t ea, PyObject *py_swi)
{
switch_info_ex_t *swi = switch_info_ex_t_get_clink(py_swi);
if ( swi == NULL )
return false;
set_switch_info_ex(ea, swi);
return true;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def del_switch_info_ex(ea):
"""
Deletes stored switch information
"""
pass
#</pydoc>
*/
void py_del_switch_info_ex(ea_t ea)
{
del_switch_info_ex(ea);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def enum_import_names(mod_index, callback):
"""
Enumerate imports from a specific module.
Please refer to ex_imports.py example.
@param mod_index: The module index
@param callback: A callable object that will be invoked with an ea, name (could be None) and ordinal.
@return: 1-finished ok, -1 on error, otherwise callback return value (<=0)
"""
pass
#</pydoc>
*/
static int py_enum_import_names(int mod_index, PyObject *py_cb)
{ {
if ( !PyCallable_Check(py_cb) ) if ( !PyCallable_Check(py_cb) )
return -1; return -1;
return enum_import_names(mod_index, py_import_enum_cb, py_cb); return enum_import_names(mod_index, py_import_enum_cb, py_cb);
} }
//-------------------------------------------------------------------------
static PyObject *switch_info_ex_t_create()
{
switch_info_ex_t *inst = new switch_info_ex_t();
return PyCObject_FromVoidPtr(inst, NULL);
}
static bool switch_info_ex_t_destroy(PyObject *py_obj)
{
if ( !PyCObject_Check(py_obj) )
return false;
switch_info_ex_t *inst = (switch_info_ex_t *) PyCObject_AsVoidPtr(py_obj);
delete inst;
return true;
}
static bool switch_info_ex_t_assign(PyObject *self, PyObject *other)
{
switch_info_ex_t *lhs = switch_info_ex_t_get_clink(self);
switch_info_ex_t *rhs = switch_info_ex_t_get_clink(other);
if (lhs == NULL || rhs == NULL)
return false;
*lhs = *rhs;
return true;
}
//-------------------------------------------------------------------------
// Auto generated - begin
//
static PyObject *switch_info_ex_t_get_regdtyp(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("b", (char)link->regdtyp);
}
static void switch_info_ex_t_set_regdtyp(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
link->regdtyp = (char)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_flags2(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("i", link->flags2);
}
static void switch_info_ex_t_set_flags2(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
link->flags2 = (int)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_jcases(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("i", link->jcases);
}
static void switch_info_ex_t_set_jcases(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
link->jcases = (int)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_regnum(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("i", (int)link->regnum);
}
static void switch_info_ex_t_set_regnum(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
link->regnum = (int)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_flags(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("H", (ushort)link->flags);
}
static void switch_info_ex_t_set_flags(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
link->flags = (uint16)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_ncases(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue("H", (uint16)link->ncases);
}
static void switch_info_ex_t_set_ncases(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
link->ncases = (ushort)PyInt_AsLong(value);
}
static PyObject *switch_info_ex_t_get_defjump(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->defjump);
}
static void switch_info_ex_t_set_defjump(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
uint64 v(0); PyGetNumber(value, &v);
link->defjump = (pyul_t)v;
}
static PyObject *switch_info_ex_t_get_jumps(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->jumps);
}
static void switch_info_ex_t_set_jumps(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
uint64 v(0); PyGetNumber(value, &v);
link->jumps = (pyul_t)v;
}
static PyObject *switch_info_ex_t_get_elbase(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->elbase);
}
static void switch_info_ex_t_set_elbase(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
uint64 v(0);
PyGetNumber(value, &v);
link->elbase = (pyul_t)v;
}
static PyObject *switch_info_ex_t_get_startea(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->startea);
}
static void switch_info_ex_t_set_startea(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
uint64 v(0);
PyGetNumber(value, &v);
link->startea = (pyul_t)v;
}
static PyObject *switch_info_ex_t_get_custom(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->custom);
}
static void switch_info_ex_t_set_custom(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
uint64 v(0);
PyGetNumber(value, &v);
link->custom = (pyul_t)v;
}
static PyObject *switch_info_ex_t_get_ind_lowcase(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->ind_lowcase);
}
static void switch_info_ex_t_set_ind_lowcase(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
uint64 v(0);
PyGetNumber(value, &v);
link->ind_lowcase = (pyul_t)v;
}
static PyObject *switch_info_ex_t_get_values_lowcase(PyObject *self)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
Py_RETURN_NONE;
return Py_BuildValue(PY_FMT64, (pyul_t)link->values);
}
static void switch_info_ex_t_set_values_lowcase(PyObject *self, PyObject *value)
{
switch_info_ex_t *link = switch_info_ex_t_get_clink(self);
if ( link == NULL )
return;
uint64 v(0);
PyGetNumber(value, &v);
link->values = (pyul_t)v;
}
//
// Auto generated - end
//
//-------------------------------------------------------------------------
//</inline(py_nalt)> //</inline(py_nalt)>
%}
%pythoncode %{
#<pycode(py_nalt)>
SWI_SPARSE = 0x1
"""sparse switch ( value table present ) otherwise lowcase present"""
SWI_V32 = 0x2
"""32-bit values in table"""
SWI_J32 = 0x4
"""32-bit jump offsets"""
SWI_VSPLIT = 0x8
"""value table is split (only for 32-bit values)"""
SWI_DEFAULT = 0x10
"""default case is present"""
SWI_END_IN_TBL = 0x20
"""switchend in table (default entry)"""
SWI_JMP_INV = 0x40
"""jumptable is inversed (last entry is for first entry in values table)"""
SWI_SHIFT_MASK = 0x180
"""use formula (element*shift + elbase) to find jump targets"""
SWI_ELBASE = 0x200
"""elbase is present (if not and shift!=0, endof(jumpea) is used)"""
SWI_JSIZE = 0x400
"""jump offset expansion bit"""
SWI_VSIZE = 0x800
"""value table element size expansion bit"""
SWI_SEPARATE = 0x1000
"""do not create an array of individual dwords"""
SWI_SIGNED = 0x2000
"""jump table entries are signed"""
SWI_CUSTOM = 0x4000
"""custom jump table - ph.create_switch_xrefs will be called to create code xrefs for the table. it must return 2. custom jump table must be created by the module"""
SWI_EXTENDED = 0x8000
"""this is switch_info_ex_t"""
SWI2_INDIRECT = 0x0001
"""value table elements are used as indexes into the jump table"""
SWI2_SUBTRACT = 0x0002
"""table values are subtracted from the elbase instead of being addded"""
# --------------------------------------------------------------------------
class switch_info_ex_t(py_clinked_object_t):
def __init__(self, lnk = None):
py_clinked_object_t.__init__(self, lnk)
def _create_clink(self):
return _idaapi.switch_info_ex_t_create()
def _del_clink(self, lnk):
return _idaapi.switch_info_ex_t_destroy(lnk)
def assign(self, other):
return _idaapi.switch_info_ex_t_assign(self, other)
def is_indirect(self):
return (self.flags & SWI_EXTENDED) != 0 and (self.flags2 & SWI2_INDIRECT) != 0
def is_subtract(self):
return (self.flags & SWI_EXTENDED) != 0 and (self.flags2 & SWI2_SUBTRACT) != 0
def get_jtable_size(self):
return self.jcases if self.is_indirect() else ncases
def get_lowcase(self):
return self.ind_lowcase if is_indirect() else self.lowcase
def set_expr(self, r, dt):
self.regnum = r
self.regdtyp = dt
def get_shift(self):
return (self.flags & SWI_SHIFT_MASK) >> 7
def set_shift(self, shift):
self.flags &= ~SWI_SHIFT_MASK
self.flags |= ((shift & 3) << 7)
def get_jtable_element_size(self):
code = self.flags & (SWI_J32|SWI_JSIZE)
if code == 0: return 2
elif code == SWI_J32: return 4
elif code == SWI_JSIZE: return 1
else: return 8
def set_jtable_element_size(self, size):
self.flags &= ~(SWI_J32|SWI_JSIZE)
if size == 4: self.flags |= SWI_J32
elif size == 1: self.flags |= SWI_JSIZE
elif size == 8: self.flags |= SWI_J32|SWI_JSIZE
elif size != 2: return False
return True
def get_vtable_element_size(self):
code = self.flags & (SWI_V32|SWI_VSIZE)
if code == 0: return 2
elif code == SWI_V32: return 4
elif code == SWI_VSIZE: return 1
return 8
def set_vtable_element_size(self, size):
self.flags &= ~SWI_V32|SWI_VSIZE
if size == 4: self.flags |= SWI_V32
elif size == 1: self.flags |= SWI_VSIZE
elif size == 8: self.flags |= SWI_V32|SWI_VSIZE
elif size != 2: return False
return True
#
# Autogenerated
#
def __get_regdtyp__(self):
return _idaapi.switch_info_ex_t_get_regdtyp(self)
def __set_regdtyp__(self, v):
_idaapi.switch_info_ex_t_set_regdtyp(self, v)
def __get_flags2__(self):
return _idaapi.switch_info_ex_t_get_flags2(self)
def __set_flags2__(self, v):
_idaapi.switch_info_ex_t_set_flags2(self, v)
def __get_jcases__(self):
return _idaapi.switch_info_ex_t_get_jcases(self)
def __set_jcases__(self, v):
_idaapi.switch_info_ex_t_set_jcases(self, v)
def __get_regnum__(self):
return _idaapi.switch_info_ex_t_get_regnum(self)
def __set_regnum__(self, v):
_idaapi.switch_info_ex_t_set_regnum(self, v)
def __get_flags__(self):
return _idaapi.switch_info_ex_t_get_flags(self)
def __set_flags__(self, v):
_idaapi.switch_info_ex_t_set_flags(self, v)
def __get_ncases__(self):
return _idaapi.switch_info_ex_t_get_ncases(self)
def __set_ncases__(self, v):
_idaapi.switch_info_ex_t_set_ncases(self, v)
def __get_defjump__(self):
return _idaapi.switch_info_ex_t_get_defjump(self)
def __set_defjump__(self, v):
_idaapi.switch_info_ex_t_set_defjump(self, v)
def __get_jumps__(self):
return _idaapi.switch_info_ex_t_get_jumps(self)
def __set_jumps__(self, v):
_idaapi.switch_info_ex_t_set_jumps(self, v)
def __get_elbase__(self):
return _idaapi.switch_info_ex_t_get_elbase(self)
def __set_elbase__(self, v):
_idaapi.switch_info_ex_t_set_elbase(self, v)
def __get_startea__(self):
return _idaapi.switch_info_ex_t_get_startea(self)
def __set_startea__(self, v):
_idaapi.switch_info_ex_t_set_startea(self, v)
def __get_custom__(self):
return _idaapi.switch_info_ex_t_get_custom(self)
def __set_custom__(self, v):
_idaapi.switch_info_ex_t_set_custom(self, v)
def __get_ind_lowcase__(self):
return _idaapi.switch_info_ex_t_get_ind_lowcase(self)
def __set_ind_lowcase__(self, v):
_idaapi.switch_info_ex_t_set_ind_lowcase(self, v)
def __get_values_lowcase__(self):
return _idaapi.switch_info_ex_t_get_values_lowcase(self)
def __set_values_lowcase__(self, v):
_idaapi.switch_info_ex_t_set_values_lowcase(self, v)
regdtyp = property(__get_regdtyp__, __set_regdtyp__)
"""size of the switch expression register as dtyp"""
flags2 = property(__get_flags2__, __set_flags2__)
jcases = property(__get_jcases__, __set_jcases__)
"""number of entries in the jump table (SWI2_INDIRECT)"""
regnum = property(__get_regnum__, __set_regnum__)
"""the switch expression as a register number"""
flags = property(__get_flags__, __set_flags__)
"""the switch expression as a register number"""
ncases = property(__get_ncases__, __set_ncases__)
"""number of cases (excluding default)"""
defjump = property(__get_defjump__, __set_defjump__)
"""default jump address"""
jumps = property(__get_jumps__, __set_jumps__)
"""jump table address"""
elbase = property(__get_elbase__, __set_elbase__)
"""element base"""
startea = property(__get_startea__, __set_startea__)
"""start of switch idiom"""
custom = property(__get_custom__, __set_custom__)
"""information for custom tables (filled and used by modules)"""
ind_lowcase = property(__get_ind_lowcase__, __set_ind_lowcase__)
values = property(__get_values_lowcase__, __set_values_lowcase__)
lowcase = property(__get_values_lowcase__, __set_values_lowcase__)
#</pycode(py_nalt)>
%} %}

View File

@ -39,6 +39,8 @@
%ignore netnode_suplast_idx8; %ignore netnode_suplast_idx8;
%ignore netnode_supprev_idx8; %ignore netnode_supprev_idx8;
%ignore netnode_supdel_all; %ignore netnode_supdel_all;
%ignore netnode_supdel_range;
%ignore netnode_supdel_range_idx8;
%ignore netnode_hashval; %ignore netnode_hashval;
%ignore netnode_hashstr; %ignore netnode_hashstr;
%ignore netnode_hashval_long; %ignore netnode_hashval_long;

View File

@ -1,5 +1,57 @@
%ignore wchar2char; %ignore wchar2char;
%ignore hit_counter_t; %ignore hit_counter_t;
%ignore print_all_counters; %ignore reg_hit_counter;
%ignore create_hit_counter;
%include "pro.h" %ignore hit_counter_timer;
%ignore print_all_counters;
%ignore incrementer_t;
%ignore reloc_info_t; // swig under mac chokes on this
%ignore qstrlen;
%ignore qstrcmp;
%ignore qstrstr;
%ignore qstrchr;
%ignore qstrrchr;
%ignore qstring;
%ignore qvector;
%ignore bytevec_t;
%ignore reloc_info_t;
%ignore relobj_t;
%ignore wchar2char;
%ignore u2cstr;
%ignore c2ustr;
%ignore utf8_unicode;
%ignore win_utf2idb;
%ignore char2oem;
%ignore oem2char;
%ignore set_codepages;
%ignore get_codepages;
%ignore convert_codepage;
%ignore test_bit;
%ignore set_bit;
%ignore clear_bit;
%ignore set_all_bits;
%ignore clear_all_bits;
%ignore interval::overlap;
%ignore interval::includes;
%ignore interval::contains;
%ignore qrotl;
%ignore qrotr;
%ignore setflag;
%ignore read2bytes;
%ignore rotate_left;
%ignore qswap;
%ignore swap32;
%ignore swap16;
%ignore swap_value;
%ignore qalloc_or_throw;
%ignore qrealloc_or_throw;
%ignore launch_process_t;
%ignore init_process;
%ignore term_process;
%ignore get_process_exit_code;
%ignore BELOW_NORMAL_PRIORITY_CLASS;
%ignore parse_command_line;
%rename (parse_command_line) py_parse_command_line;
%include "pro.h"

View File

@ -10,10 +10,8 @@
%ignore queue_del; %ignore queue_del;
%ignore mark_rollback; %ignore mark_rollback;
%ignore get_rollback_type;
%ignore mark_ida_decision; %ignore mark_ida_decision;
%ignore unmark_ida_decision; %ignore unmark_ida_decision;
%ignore had_rolled_back;
%ignore ever_rolled_back;
%include "queue.hpp" %include "queue.hpp"

View File

@ -2,6 +2,7 @@
%ignore createSRarea; %ignore createSRarea;
%ignore killSRareas; %ignore killSRareas;
%ignore delSRarea; %ignore delSRarea;
%ignore splitSRarea;
%ignore SRareaStart; %ignore SRareaStart;
%ignore SRareaEnd; %ignore SRareaEnd;
%ignore repairSRarea; %ignore repairSRarea;

View File

@ -1,11 +1,11 @@
// Ignore kernel-only symbol // Ignore kernel-only symbol
%ignore strwinsetup_t::setup_strings_window; %ignore strwinsetup_t::setup_strings_window;
%ignore strwinsetup_t::save_config; %ignore strwinsetup_t::save_config;
%ignore strwinsetup_t::restore_config; %ignore strwinsetup_t::restore_config;
%ignore move_strings; %ignore move_strings;
%include "strlist.hpp" %include "strlist.hpp"

View File

@ -113,7 +113,10 @@
%ignore get_struct_member; %ignore get_struct_member;
%ignore idb_type_to_til; %ignore idb_type_to_til;
%ignore get_idb_type; %ignore get_idb_type;
%ignore apply_type_to_stkarg; %ignore apply_type_to_stkarg;
%rename (apply_type_to_stkarg) py_apply_type_to_stkarg;
%ignore use_regarg_type_cb; %ignore use_regarg_type_cb;
%ignore set_op_type_t; %ignore set_op_type_t;
%ignore is_stkarg_load_t; %ignore is_stkarg_load_t;
@ -144,23 +147,6 @@
%include "typeinf.hpp" %include "typeinf.hpp"
%{
//<code(py_typeinf)>
//-------------------------------------------------------------------------
// Utility function to convert a python object to an IDC object
// and sets a python exception on failure.
static bool convert_pyobj_to_idc_exc(PyObject *py_obj, idc_value_t *idc_obj)
{
int sn = 0;
if (pyvar_to_idcvar(py_obj, idc_obj, &sn) < CIP_OK)
{
PyErr_SetString(PyExc_ValueError, "Could not convert Python object to IDC object!");
return false;
}
return true;
}
//</code(py_typeinf)>
%}
// Custom wrappers // Custom wrappers
%rename (load_til) load_til_wrap; %rename (load_til) load_til_wrap;
@ -177,18 +163,32 @@ PyObject *idc_parse_decl(til_t *ti, const char *decl, int flags)
qtype fields, type; qtype fields, type;
qstring name; qstring name;
bool ok = parse_decl(ti, decl, &name, &type, &fields, flags); bool ok = parse_decl(ti, decl, &name, &type, &fields, flags);
if (!ok) if ( !ok )
Py_RETURN_NONE; Py_RETURN_NONE;
return Py_BuildValue("(sss)", return Py_BuildValue("(sss)",
name.c_str(), name.c_str(),
(char *)type.c_str(), (char *)type.c_str(),
(char *)fields.c_str()); (char *)fields.c_str());
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/*
#<pydoc>
def get_type_size0(ti, tp):
"""
Returns the size of a type
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@param tp: type string
@return:
- None on failure
- The size of the type
"""
pass
#</pydoc>
*/
PyObject *py_get_type_size0(const til_t *ti, PyObject *tp) PyObject *py_get_type_size0(const til_t *ti, PyObject *tp)
{ {
if (!PyString_Check(tp)) if ( !PyString_Check(tp) )
{ {
PyErr_SetString(PyExc_ValueError, "String expected!"); PyErr_SetString(PyExc_ValueError, "String expected!");
return NULL; return NULL;
@ -200,13 +200,22 @@ PyObject *py_get_type_size0(const til_t *ti, PyObject *tp)
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Read a typed idc object from the database /*
#<pydoc>
def py_unpack_object_from_idb(ti, tp, fields, ea, pio_flags = 0):
"""
Unpacks from the database at 'ea' to an object.
Please refer to unpack_object_from_bv()
"""
pass
#</pydoc>
*/
PyObject *py_unpack_object_from_idb( PyObject *py_unpack_object_from_idb(
til_t *ti, til_t *ti,
PyObject *py_type, PyObject *py_type,
PyObject *py_fields, PyObject *py_fields,
ea_t ea, ea_t ea,
int pio_flags) int pio_flags = 0)
{ {
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) ) if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{ {
@ -236,13 +245,30 @@ PyObject *py_unpack_object_from_idb(
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Read a typed idc object from the byte vector /*
#<pydoc>
def unpack_object_from_bv(ti, tp, fields, bytes, pio_flags = 0):
"""
Unpacks a buffer into an object.
Returns the error_t returned by idaapi.pack_object_to_idb
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@param tp: type string
@param fields: type fields
@param bytes: the bytes to unpack
@param pio_flags: flags used while unpacking
@return:
- tuple(0, err) on failure
- tuple(1, obj) on success
"""
pass
#</pydoc>
*/
PyObject *py_unpack_object_from_bv( PyObject *py_unpack_object_from_bv(
til_t *ti, til_t *ti,
PyObject *py_type, PyObject *py_type,
PyObject *py_fields, PyObject *py_fields,
PyObject *py_bytes, PyObject *py_bytes,
int pio_flags) int pio_flags = 0)
{ {
if ( !PyString_Check(py_type) && !PyString_Check(py_fields) && !PyString_Check(py_bytes) ) if ( !PyString_Check(py_type) && !PyString_Check(py_fields) && !PyString_Check(py_bytes) )
{ {
@ -278,18 +304,31 @@ PyObject *py_unpack_object_from_bv(
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
// Write a typed idc object to the database /*
// Raises an exception if wrong parameters were passed or conversion fails #<pydoc>
// Returns the error_t returned by idasdk.pack_object_to_idb def pack_object_to_idb(obj, ti, tp, fields, ea, pio_flags = 0):
"""
Write a typed object to the database.
Raises an exception if wrong parameters were passed or conversion fails
Returns the error_t returned by idaapi.pack_object_to_idb
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@param tp: type string
@param fields: type fields
@param ea: ea to be used while packing
@param pio_flags: flags used while unpacking
"""
pass
#</pydoc>
*/
PyObject *py_pack_object_to_idb( PyObject *py_pack_object_to_idb(
PyObject *py_obj, PyObject *py_obj,
til_t *ti, til_t *ti,
PyObject *py_type, PyObject *py_type,
PyObject *py_fields, PyObject *py_fields,
ea_t ea, ea_t ea,
int pio_flags) int pio_flags = 0)
{ {
if (!PyString_Check(py_type) && !PyString_Check(py_fields)) if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{ {
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!"); PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL; return NULL;
@ -297,7 +336,7 @@ PyObject *py_pack_object_to_idb(
// Convert Python object to IDC object // Convert Python object to IDC object
idc_value_t idc_obj; idc_value_t idc_obj;
if (!convert_pyobj_to_idc_exc(py_obj, &idc_obj)) if ( !convert_pyobj_to_idc_exc(py_obj, &idc_obj) )
return NULL; return NULL;
// Get type strings // Get type strings
@ -310,6 +349,23 @@ PyObject *py_pack_object_to_idb(
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
/*
#<pydoc>
def pack_object_to_bv(obj, ti, tp, fields, ea, pio_flags = 0):
"""
Packs a typed object to a string
@param ti: Type info. 'idaapi.cvar.idati' can be passed.
@param tp: type string
@param fields: type fields
@param ea: ea to be used while packing
@param pio_flags: flags used while unpacking
@return:
tuple(0, err_code) on failure
tuple(1, packed_buf) on success
"""
pass
#</pydoc>
*/
// Returns a tuple(Boolean, PackedBuffer or Error Code) // Returns a tuple(Boolean, PackedBuffer or Error Code)
PyObject *py_pack_object_to_bv( PyObject *py_pack_object_to_bv(
PyObject *py_obj, PyObject *py_obj,
@ -319,7 +375,7 @@ PyObject *py_pack_object_to_bv(
ea_t base_ea, ea_t base_ea,
int pio_flags=0) int pio_flags=0)
{ {
if (!PyString_Check(py_type) && !PyString_Check(py_fields)) if ( !PyString_Check(py_type) && !PyString_Check(py_fields) )
{ {
PyErr_SetString(PyExc_ValueError, "Typestring must be passed!"); PyErr_SetString(PyExc_ValueError, "Typestring must be passed!");
return NULL; return NULL;
@ -327,7 +383,7 @@ PyObject *py_pack_object_to_bv(
// Convert Python object to IDC object // Convert Python object to IDC object
idc_value_t idc_obj; idc_value_t idc_obj;
if (!convert_pyobj_to_idc_exc(py_obj, &idc_obj)) if ( !convert_pyobj_to_idc_exc(py_obj, &idc_obj) )
return NULL; return NULL;
// Get type strings // Get type strings
@ -337,24 +393,24 @@ PyObject *py_pack_object_to_bv(
// Pack // Pack
relobj_t bytes; relobj_t bytes;
error_t err = pack_object_to_bv( error_t err = pack_object_to_bv(
&idc_obj, &idc_obj,
ti, ti,
type, type,
fields, fields,
&bytes, &bytes,
NULL, NULL,
pio_flags); pio_flags);
do do
{ {
if (err != eOk) if ( err != eOk )
break; break;
if (!bytes.relocate(base_ea, inf.mf)) if ( !bytes.relocate(base_ea, inf.mf) )
{ {
err = -1; err = -1;
break; break;
} }
return Py_BuildValue("(is#)", 1, bytes.begin(), bytes.size()); return Py_BuildValue("(is#)", 1, bytes.begin(), bytes.size());
} while (false); } while ( false );
return Py_BuildValue("(ii)", 0, err); return Py_BuildValue("(ii)", 0, err);
} }
//</inline(py_typeinf)> //</inline(py_typeinf)>

1369
swig/ua.i

File diff suppressed because it is too large Load Diff

View File

@ -9,6 +9,8 @@
%ignore has_jump_or_flow_xref; %ignore has_jump_or_flow_xref;
%ignore has_call_xref; %ignore has_call_xref;
%ignore destroy_switch_info; %ignore destroy_switch_info;
%ignore create_switch_xrefs;
%ignore create_switch_table;
// These functions should not be called directly (according to docs) // These functions should not be called directly (according to docs)
%ignore xrefblk_t_first_from; %ignore xrefblk_t_first_from;

85
tools/swigdocs.py Normal file
View File

@ -0,0 +1,85 @@
# -----------------------------------------------------------------------
# This script is used to extract embedded documentation strings
# from SWIG interface files.
# (c) Hex-Rays
#
import glob
import sys
# ---------------------------------------------------------------------------
def extract_docs(lines, out):
S_SWIG_CLOSE = '%}'
S_PYDOC_START = '#<pydoc>'
S_PYDOC_END = '#</pydoc>'
S_COMMENT = '#'
S_INLINE = '%inline %{'
S_PYCODE_START = '%pythoncode %{'
in_inline = False
in_pythoncode = False
in_pydoc = False
for line in lines:
line = line.rstrip()
# skip empty lines
if not line:
continue
# Inside pythoncode tag?
if in_pythoncode:
if line == S_PYDOC_START:
in_pydoc = True
continue
elif line == S_PYDOC_END:
in_pydoc = False
continue
elif line == S_SWIG_CLOSE:
in_pythoncode = False
continue
# Skip unneeded tags
elif line[:8] == '#<pycode' or line[:9] == '#</pycode':
continue
# In pydoc? uncomment the lines
elif in_pydoc:
if line[0] == S_COMMENT:
line = line[1:]
# All lines in pythoncode section are extracted
out.append(line)
# Inside inline tag?
elif in_inline:
if line == S_PYDOC_START:
in_pydoc = True
continue
elif line == S_SWIG_CLOSE:
in_inline = False
continue
elif line == S_PYDOC_END:
in_pydoc = False
continue
# Extract lines in cpydoc only
elif in_pydoc:
out.append(line)
# Detect tags
elif line == S_PYCODE_START:
in_pythoncode = True
continue
elif line == S_INLINE:
in_inline = True
# ---------------------------------------------------------------------------
def gen_docs(path = '../swig/', outfn = 'idaapi.py', mask = '*.i'):
out = []
for fn in glob.glob(path + mask):
f = open(fn, 'r')
lines = f.readlines()
f.close()
extract_docs(lines, out)
f = open(outfn, 'w')
f.write('"""This is a placeholder module used to document all the IDA SDK functions that are wrapped manually. You still need to import \'idaapi\' and not this module to use the functions"""\n')
f.write('\n'.join(out))
f.close()
if __name__ == '__main__':
gen_docs(mask='idaapi.i')