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
----------------------------------------------------------
Building From Source
--------------------
REQUIREMENTS
------------
[Tested versions are in brackets]
- IDA and IDA SDK [5.6]
http://www.hex-rays.com/idapro/
- Python [2.5.1, 2.6.1]
http://www.python.org/
- Simplified Wrapper Interface Generator (SWIG) [1.3.36]
http://www.swig.org/
- Unix utilities (GNU patch on Windows):
http://www.research.att.com/sw/tools/uwin/ or
http://unxutils.sourceforge.net/ or
http://www.cygwin.com/
- GCC on Linux and Mac OS X [4.0.1, 4.1.3]
Comes with your distribution
- Microsoft Visual C on Windows [Microsoft Visual C++ 2008 Express Edition]
http://msdn.microsoft.com/vstudio/express/visualc/
BUILDING
--------
Make sure all the needed tools (compiler, swig) are on the PATH.
1, Unpack the IDAPython source and IDA Pro SDK into the following
directory structure:
swigsdk-versions/5.6/ - version 5.6 of the IDA Pro SDK
idapython/ - IDAPython source code
2, On Mac OS X copy libida.dylib from the IDA install directory to
swigsdk-versions/5.6/lib/gcc32.mac/
and libida64.dylib to
swigsdk-versions/5.6/lib/gcc64.mac/
3, Build the plugin
python build.py
It is possible to build the plugin for different Python versions by
running build.py with the corresponding Python binary.
Some build options:
--ea64: builds the 64-bit version
--no-early-load: builds the IDAPython plugin w/o PLUGIN_FIX plugin flag
(This flag disables the ability to write file loaders in IDAPython)
4, Install the components as described in README.txt
See build.py for build details and possible tweaks.
----------------------------------------------------------
IDAPython - Python plugin for Interactive Disassembler Pro
----------------------------------------------------------
Building From Source
--------------------
REQUIREMENTS
------------
[Tested versions are in brackets]
- IDA and IDA SDK [5.6]
http://www.hex-rays.com/idapro/
- Python [2.5.1, 2.6.1]
http://www.python.org/
- Simplified Wrapper Interface Generator (SWIG) [1.3.36]
http://www.swig.org/
- Unix utilities (GNU patch on Windows):
http://www.research.att.com/sw/tools/uwin/ or
http://unxutils.sourceforge.net/ or
http://www.cygwin.com/
- GCC on Linux and Mac OS X [4.0.1, 4.1.3]
Comes with your distribution
- Microsoft Visual C on Windows [Microsoft Visual C++ 2008 Express Edition]
http://msdn.microsoft.com/vstudio/express/visualc/
BUILDING
--------
Make sure all the needed tools (compiler, swig) are on the PATH.
1, Unpack the IDAPython source and IDA Pro SDK into the following
directory structure:
swigsdk-versions/5.6/ - version 5.6 of the IDA Pro SDK
idapython/ - IDAPython source code
2, On Mac OS X copy libida.dylib from the IDA install directory to
swigsdk-versions/5.6/lib/gcc32.mac/
and libida64.dylib to
swigsdk-versions/5.6/lib/gcc64.mac/
3, Build the plugin
python build.py
It is possible to build the plugin for different Python versions by
running build.py with the corresponding Python binary.
Run 'build.py --help' for more information.
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
detailed list of changes.
Changes from version 1.2.0 to 1.3.0
------------------------------------
- IDA Pro 5.6 support
- Added Appcall mechanism
- Added procregs to idautils.py (r254)
- Lots of cleanups and fixes
Changes from version 1.1.0 to 1.2.0
------------------------------------
- 64-bit support (largely untested)
- IDA Pro 5.5 support
- Long running (or inifinitely looping) scripts can now be stopped
- Host of IDC updates and fixes
- netnode.hpp is now mostly wrapped
- idautils use generators instead of lists
- Functions() and GetFchunkAttr() now work properly
- Lots of cleanups and fixes
Changes from version 0.9.0 to 1.0.0
-----------------------------------
- Upgraded IDA Pro base version to 5.1
- Dropped Python 2.4 support
- Mac OS X support
- 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
- Support for GUI hotkeys (see examples/hotkey.py)
- Simple two-way calling mechanism between IDC and IDAPython
- Significantly better IDA API coverage
- Support for IDB and debug event hooks
- get_current_instruction() deprecated, use the idaapi.cvar.cmd variable
- Tons of IDC fixes
- Tons of other misc fixes
Changes from version 0.8.0 to 0.9.0
-----------------------------------
- Upgraded base version to IDA Pro 5.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)
- Significatnly improved IDA SDK API covergage (see STATUS.txt for details)
- IDA SDK patch size reduced to less than half
- Simplified installation (plugins.cfg modification not needed)
- 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
- Cleanups and small fixes
Changes from version 0.7.0 to 0.8.0
-----------------------------------
- Added support for IDA Pro 4.9
- Dropped support for IDA Pro 4.7
- NOTE: Windows version is linked against Python 2.4.
- New wrappers: search.hpp, dbg.hpp, loader.hpp, diskio.hpp, nalt.hpp
- idc.py synced up to IDA 4.8
- Added 38 IDC functions
- Fixed asklong(), askseg() and askaddr()
- 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)
- Fixed exception in ScriptBox when invoked empty.
- Lots of cleanups and small fixes
Changes from version 0.6.0 to 0.7.0
-----------------------------------
- Batch execution support (use the option -OIDAPython:yourscript.py)
- Added ScriptBox - lists previously run scripts (Hotkey:Alt-7)
- Added support for IDA Pro 4.8 (both Linux and Windows)
- Dropped support for IDA Pro 4.6 and 4.6SP1 versions
- Wrapped the list chooser (see examples/choose.py)
- A dozen or so IDC functions added
- Lots of char * API calls wrapped
- Added Python error handling in the plugin C layer
- Bunch of misc small cleanups and fixes
- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt
- API CHANGE: {Next|Prev}Function() return BADADDR instead of -1
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
Please see http://code.google.com/p/idapython/source/list for a detailed list of changes.
Changes from version 1.3.0 to 1.4.0
------------------------------------
- IDA Pro 5.7 support
- idaapi.cvar.cmd is now accessible via idapi.cmd instead
- Python statement (Alt-8) is now 16kb long
- Dropped script box and File/Python file. IDA has this functionality now.
- Refactored the code
- It is possible to turn off script timeout
- All scripts are executed via 'IDAPython_ExecScript' (check idaapi.i)
- Added '--doc' switch to "build.py" script
- Documented all manually wrapped functions (check 'pywraps' module in the docs)
- Lots of cleanups and fixes
Changes from version 1.2.0 to 1.3.0
------------------------------------
- IDA Pro 5.6 support
- Added Appcall mechanism
- Added procregs to idautils.py (r254)
- Lots of cleanups and fixes
Changes from version 1.1.0 to 1.2.0
------------------------------------
- 64-bit support (largely untested)
- IDA Pro 5.5 support
- Long running (or inifinitely looping) scripts can now be stopped
- Host of IDC updates and fixes
- netnode.hpp is now mostly wrapped
- idautils use generators instead of lists
- Functions() and GetFchunkAttr() now work properly
- Lots of cleanups and fixes
Changes from version 0.9.0 to 1.0.0
-----------------------------------
- Upgraded IDA Pro base version to 5.1
- Dropped Python 2.4 support
- Mac OS X support
- 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
- Support for GUI hotkeys (see examples/hotkey.py)
- Simple two-way calling mechanism between IDC and IDAPython
- Significantly better IDA API coverage
- Support for IDB and debug event hooks
- get_current_instruction() deprecated, use the idaapi.cvar.cmd variable
- Tons of IDC fixes
- Tons of other misc fixes
Changes from version 0.8.0 to 0.9.0
-----------------------------------
- Upgraded base version to IDA Pro 5.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)
- Significatnly improved IDA SDK API covergage (see STATUS.txt for details)
- IDA SDK patch size reduced to less than half
- Simplified installation (plugins.cfg modification not needed)
- 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
- Cleanups and small fixes
Changes from version 0.7.0 to 0.8.0
-----------------------------------
- Added support for IDA Pro 4.9
- Dropped support for IDA Pro 4.7
- NOTE: Windows version is linked against Python 2.4.
- New wrappers: search.hpp, dbg.hpp, loader.hpp, diskio.hpp, nalt.hpp
- idc.py synced up to IDA 4.8
- Added 38 IDC functions
- Fixed asklong(), askseg() and askaddr()
- 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)
- Fixed exception in ScriptBox when invoked empty.
- Lots of cleanups and small fixes
Changes from version 0.6.0 to 0.7.0
-----------------------------------
- Batch execution support (use the option -OIDAPython:yourscript.py)
- Added ScriptBox - lists previously run scripts (Hotkey:Alt-7)
- Added support for IDA Pro 4.8 (both Linux and Windows)
- Dropped support for IDA Pro 4.6 and 4.6SP1 versions
- Wrapped the list chooser (see examples/choose.py)
- A dozen or so IDC functions added
- Lots of char * API calls wrapped
- Added Python error handling in the plugin C layer
- Bunch of misc small cleanups and fixes
- For more details see CHANGES-SWIG.txt and CHANGES-Plugin.txt
- API CHANGE: {Next|Prev}Function() return BADADDR instead of -1
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.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
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
OF SUCH DAMAGE.
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
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
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
OF SUCH DAMAGE.

View File

@ -1,86 +1,86 @@
----------------------------------------------------------
IDAPython - Python plugin for Interactive Disassembler Pro
----------------------------------------------------------
WHAT IS IDAPTYHON?
------------------
IDAPython is an IDA plugin which makes it possible to write scripts
for IDA in the Python programming language. IDAPython provides full
access to both the IDA API and any installed Python module.
Check the scripts in the examples directory to get an quick glimpse.
AVAILABILITY
------------
Latest stable versions of IDAPython are available from
http://www.d-dome.net/idapython/
Development builds are available from
http://code.google.com/p/idapython/
RESOURCES
---------
The full function cross-reference is readable online at
http://www.d-dome.net/idapython/reference/
Bugs and enhancement requests should be submitted to
http://code.google.com/p/idapython/issues/list
Mailing list for the project is hosted by Google Groups at
http://groups.google.com/group/idapython
INSTALLATION FROM BINARIES
--------------------------
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
3. Copy the plugins to the %IDADIR%\plugins\
USAGE
-----
The plugin has three hotkeys:
- Run script (Alt-9)
- Execute Python statement(s) (Alt-8)
- Run previously executed script again (Alt-7)
Batch mode execution:
Start IDA with the following command line options:
-A -OIDAPython:yourscript.py file_to_work_on
If you want fully unattended execution mode, make sure your script
exits with a qexit() call.
By default scripts run after the database is opened. Extended option
format is:
-OIDAPython:[N;]script.py
Where N can be:
0: run script after opening database (default)
1: run script when UI is ready
2: run script immediately on plugin load (shortly after IDA starts and before processor modules and loaders)
User init file:
You can place your custom settings to a file called 'idapythonrc.py'
that should be placed to
${HOME}/.idapro/
or
%AppData%\Hex-Rays\IDA Pro
The user init file is read and executed at the end of the init process.
----------------------------------------------------------
IDAPython - Python plugin for Interactive Disassembler Pro
----------------------------------------------------------
WHAT IS IDAPTYHON?
------------------
IDAPython is an IDA plugin which makes it possible to write scripts
for IDA in the Python programming language. IDAPython provides full
access to both the IDA API and any installed Python module.
Check the scripts in the examples directory to get an quick glimpse.
AVAILABILITY
------------
Latest stable versions of IDAPython are available from
http://www.d-dome.net/idapython/
Development builds are available from
http://code.google.com/p/idapython/
RESOURCES
---------
The full function cross-reference is readable online at
http://www.d-dome.net/idapython/reference/
Bugs and enhancement requests should be submitted to
http://code.google.com/p/idapython/issues/list
Mailing list for the project is hosted by Google Groups at
http://groups.google.com/group/idapython
INSTALLATION FROM BINARIES
--------------------------
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
3. Copy the plugins to the %IDADIR%\plugins\
USAGE
-----
The plugin has three hotkeys:
- Run script (Alt-9)
- Execute Python statement(s) (Alt-8)
- Run previously executed script again (Alt-7)
Batch mode execution:
Start IDA with the following command line options:
-A -OIDAPython:yourscript.py file_to_work_on
If you want fully unattended execution mode, make sure your script
exits with a qexit() call.
By default scripts run after the database is opened. Extended option
format is:
-OIDAPython:[N;]script.py
Where N can be:
0: run script after opening database (default)
1: run script when UI is ready
2: run script immediately on plugin load (shortly after IDA starts and before processor modules and loaders)
User init file:
You can place your custom settings to a file called 'idapythonrc.py'
that should be placed to
${HOME}/.idapro/
or
%AppData%\Hex-Rays\IDA Pro
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
-----------------------
The IDC emulation layer is complete and at par with IDA 5.1,
although it would benefit from more testing.
Status of IDA API wrappers
--------------------------
COMPLETE: all possible functions wrapped, no SWIG ifdefs
INCOMPLETE: some wrapping or SWIG ifdefs still left
EXCLUDED: will not be wrapped
allins.hpp - COMPLETE
area.hpp - COMPLETE (necessary SWIGdefs)
auto.hpp - COMPLETE
bytes.hpp - COMPLETE (some minor unwrapped)
compress.hpp - EXCLUDED
dbg.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
demangle.hpp - EXCLUDED
diskio.hpp - INCOMPLETE (no SWIGs, some unwrapped)
entry.hpp - COMPLETE
enum.hpp - COMPLETE
err.h - EXCLUDED
exehdr.h - EXCLUDED
expr.hpp - COMPLETE (necessary SWIGs)
fixup.hpp - COMPLETE
fpro.h - EXCLUDED
frame.hpp - COMPLETE
funcs.hpp - COMPLETE (necessary SWIGs, minor FIXME)
gdl.hpp - EXCLUDED
graph.hpp - INCOMPLETE
help.h - EXCLUDED
ida.hpp - COMPLETE
idd.hpp - COMPLETE (necessary SWIGs)
idp.hpp - COMPLETE
ieee.h - EXCLUDED
intel.hpp - EXCLUDED
ints.hpp - COMPLETE
kernwin.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
lex.hpp - EXCLUDED
lines.hpp - INCOMPLETE (few FIXMEs)
llong.hpp - EXCLUDED
loader.hpp - INCOMPLETE (few FIXMEs)
md5.h - EXCLUDED
moves.hpp - COMPLETE (some needed SWIGs)
nalt.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
name.hpp - INCOMPLETE (few FIXMEs)
netnode.hpp - COMPLETE
offset.hpp - COMPLETE
prodir.h - EXCLUDED
pro.h - COMPLETE (some needed SWIGs)
queue.hpp - INCOMPLETE (one FIXME)
regex.h - EXCLUDED
search.hpp - COMPLETE
segment.hpp - COMPLETE
sistack.hpp - EXCLUDED
srarea.hpp - INCOMPLETE (not wrapped at all)
strlist.hpp - COMPLETE
struct.hpp - COMPLETE
typeinf.hpp - INCOMPLETE (no SWIGs, lot of fixing to do)
ua.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
va.hpp - EXCLUDED
vm.hpp - EXCLUDED
xref.hpp - COMPLETE
Status of the IDC layer
-----------------------
The IDC emulation layer is complete and at par with IDA 5.1,
although it would benefit from more testing.
Status of IDA API wrappers
--------------------------
COMPLETE: all possible functions wrapped, no SWIG ifdefs
INCOMPLETE: some wrapping or SWIG ifdefs still left
EXCLUDED: will not be wrapped
allins.hpp - COMPLETE
area.hpp - COMPLETE (necessary SWIGdefs)
auto.hpp - COMPLETE
bytes.hpp - COMPLETE (some minor unwrapped)
compress.hpp - EXCLUDED
dbg.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
demangle.hpp - EXCLUDED
diskio.hpp - INCOMPLETE (no SWIGs, some unwrapped)
entry.hpp - COMPLETE
enum.hpp - COMPLETE
err.h - EXCLUDED
exehdr.h - EXCLUDED
expr.hpp - COMPLETE (necessary SWIGs)
fixup.hpp - COMPLETE
fpro.h - EXCLUDED
frame.hpp - COMPLETE
funcs.hpp - COMPLETE (necessary SWIGs, minor FIXME)
gdl.hpp - EXCLUDED
graph.hpp - INCOMPLETE
help.h - EXCLUDED
ida.hpp - COMPLETE
idd.hpp - COMPLETE (necessary SWIGs)
idp.hpp - COMPLETE
ieee.h - EXCLUDED
intel.hpp - EXCLUDED
ints.hpp - COMPLETE
kernwin.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
lex.hpp - EXCLUDED
lines.hpp - INCOMPLETE (few FIXMEs)
llong.hpp - EXCLUDED
loader.hpp - INCOMPLETE (few FIXMEs)
md5.h - EXCLUDED
moves.hpp - COMPLETE (some needed SWIGs)
nalt.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
name.hpp - INCOMPLETE (few FIXMEs)
netnode.hpp - COMPLETE
offset.hpp - COMPLETE
prodir.h - EXCLUDED
pro.h - COMPLETE (some needed SWIGs)
queue.hpp - INCOMPLETE (one FIXME)
regex.h - EXCLUDED
search.hpp - COMPLETE
segment.hpp - COMPLETE
sistack.hpp - EXCLUDED
srarea.hpp - INCOMPLETE (not wrapped at all)
strlist.hpp - COMPLETE
struct.hpp - COMPLETE
typeinf.hpp - INCOMPLETE (no SWIGs, lot of fixing to do)
ua.hpp - INCOMPLETE (SWIGs and lot of fixing to do)
va.hpp - EXCLUDED
vm.hpp - EXCLUDED
xref.hpp - COMPLETE

View File

@ -17,12 +17,15 @@ import shutil
import sys
import types
import zipfile
import glob
from distutils import sysconfig
# Start of user configurable options
VERBOSE = True
IDA_MAJOR_VERSION = 5
IDA_MINOR_VERSION = 6
IDA_MINOR_VERSION = 7
if 'IDA' in os.environ:
IDA_SDK = os.environ['IDA']
else:
@ -32,8 +35,8 @@ else:
# IDAPython version
VERSION_MAJOR = 1
VERSION_MINOR = 3
VERSION_PATCH = 2
VERSION_MINOR = 4
VERSION_PATCH = 0
# Determine Python version
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')
# 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 = [
@ -75,6 +78,7 @@ BINDIST_MANIFEST = [
"examples/structure.py",
"examples/ex_gdl_qflow_chart.py",
"examples/ex_strings.py",
"examples/ex_add_menu_item.py",
"examples/ex_func_chooser.py",
"examples/ex_choose2.py",
"examples/ex_debug_names.py",
@ -162,7 +166,8 @@ class BuilderBase:
includestring,
macrostring)
if VERBOSE: print cmdstring
if VERBOSE:
print cmdstring
return os.system(cmdstring)
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"])
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():
if '--help' in sys.argv:
return usage()
elif '--doc' in sys.argv:
return gen_docs(z = '--zip' in sys.argv)
# Do 64-bit build?
ea64 = '--ea64' in sys.argv
build_binary_package(ea64=False, nukeold=True)
@ -422,4 +493,4 @@ def main():
build_source_package()
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:
title += " %d" % sn
# Create the customview
# Create the customviewer
if not simplecustviewer_t.Create(self, title):
return False
self.menu_hello = self.AddPopupMenu("Hello")
@ -24,6 +24,8 @@ class mycv_t(simplecustviewer_t):
for i in xrange(0, 100):
self.AddLine("Line %d" % i)
# self.Jump(0)
return True
def OnClick(self, shift):
@ -71,6 +73,7 @@ class mycv_t(simplecustviewer_t):
# ESCAPE?
if vkey == 27:
self.Close()
# VK_DELETE
elif vkey == 46:
n = self.GetLineNo()
if n is not None:
@ -129,10 +132,10 @@ class mycv_t(simplecustviewer_t):
Hint requested for the given line number.
@param lineno: The line number (zero based)
@return:
- string: a string containing the hint
- tuple(number of important lines, hint string)
- None: if no hint available
"""
return "OnHint, line=%d" % lineno
return (1, "OnHint, line=%d" % lineno)
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
# -----------------------------------------------------------------------
# IDAPython - Python plugin for Interactive Disassembler Pro
#
# Copyright (c) 2004-2010 Gergely Erdelyi <gergely.erdelyi@d-dome.net>
#
# All rights reserved.
#
# For detailed copyright information see the file COPYING in
# the root of the distribution archive.
# -----------------------------------------------------------------------
# init.py - Essential init routines
# -----------------------------------------------------------------------
import os
import sys
import time
import warnings
import _idaapi
# __EA64__ is set if IDA is running in 64-bit mode
__EA64__ = _idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL
# -----------------------------------------------------------------------
def addscriptpath(script):
"""
Add the path part of the scriptfile to the system path to
allow modules to be loaded from the same place.
Each path is added only once.
"""
pathfound = 0
scriptpath = os.path.dirname(script)
for pathitem in sys.path:
if pathitem == scriptpath:
pathfound = 1
break
if pathfound == 0:
sys.path.append(scriptpath)
# Add the script to ScriptBox if it's not there yet
if not script in scriptbox.list:
scriptbox.list.insert(0, script)
# ------------------------------------------------------------
def runscript(script):
"""
Run the specified script after adding its directory path to
system path.
This function is used by the low-level plugin code.
"""
addscriptpath(script)
watchdog.reset()
# Save the argv, path, I/O and base modules for later cleanup
argv = sys.argv
path = sys.path
stdio = [sys.stdin, sys.stdout, sys.stderr]
basemodules = sys.modules.copy()
sys.argv = [ script ]
# Adjust the __file__ path in the globals we pass to the script
g = globals()
old__file__ = g['__file__'] if '__file__' in g else ''
g['__file__'] = script
try:
execfile(script, g)
except:
raise
finally:
# Restore the globals to the state before the script was run
g['__file__'] = old__file__
sys.argv = argv
sys.path = path
sys.stdin, sys.stdout, sys.stderr = stdio
# Clean up the modules loaded by the script
for module in sys.modules.keys():
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.
#!/usr/bin/env python
# -----------------------------------------------------------------------
# IDAPython - Python plugin for Interactive Disassembler Pro
#
# Copyright (c) 2004-2010 Gergely Erdelyi <gergely.erdelyi@d-dome.net>
#
# All rights reserved.
#
# For detailed copyright information see the file COPYING in
# the root of the distribution archive.
# -----------------------------------------------------------------------
# init.py - Essential init routines
# -----------------------------------------------------------------------
import os
import sys
import time
import warnings
import _idaapi
# __EA64__ is set if IDA is running in 64-bit mode
__EA64__ = _idaapi.BADADDR == 0xFFFFFFFFFFFFFFFFL
# -----------------------------------------------------------------------
# Take over the standard text outputs
# -----------------------------------------------------------------------
class IDAPythonStdOut:
"""
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
# -----------------------------------------------------------------------
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
# -----------------------------------------------------------------------
# Redirect stderr and stdout to the IDA message window
sys.stdout = sys.stderr = IDAPythonStdOut()
# 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
# Load the users personal init file
userrc = get_user_idadir() + os.sep + "idapythonrc.py"
if os.path.exists(userrc):
idaapi.IDAPython_ExecScript(userrc, globals())
# All done, ready to rock.

View File

@ -7,17 +7,25 @@
#define PYUL_DEFINED
#ifdef __EA64__
typedef unsigned PY_LONG_LONG pyul_t;
typedef PY_LONG_LONG pyl_t;
#else
typedef unsigned long pyul_t;
typedef long pyl_t;
#endif
#endif
#ifdef __EA64__
#define PY_FMT64 "K"
#define PY_FMT64 "K"
#define PY_SFMT64 "L"
#else
#define PY_FMT64 "k"
#define PY_FMT64 "k"
#define PY_SFMT64 "l"
#endif
#define S_IDAAPI_MODNAME "idaapi"
#define S_IDC_MODNAME "idc"
#define S_IDAAPI_EXECSCRIPT "IDAPython_ExecScript"
// Vector of PyObject*
typedef qvector<PyObject *> ppyobject_vec_t;
@ -27,6 +35,19 @@ typedef qvector<PyObject *> ppyobject_vec_t;
#define PY_ICID_BYREF 1
#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
#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
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
PyObject *PyImport_TryImportModule(const char *name);
// Tries to get an attribute and swallows the exception if it fails and returns NULL
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)
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
bool PyGetNumber(PyObject *py_var, uint64 *num, bool *is_64 = NULL);
// Checks if an Python object can be treated like a sequence
bool PyIsSequenceType(PyObject *obj);
// Returns an error string from the last exception (and clears it)
bool PyGetError(qstring *out = NULL);
PyObject *PyImport_TryImportModule(const char *name);
// Tries to get an attribute and swallows the exception if it fails and returns NULL
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)
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
bool PyGetNumber(PyObject *py_var, uint64 *num, bool *is_64 = NULL);
// Checks if an Python object can be treated like a sequence
bool PyIsSequenceType(PyObject *obj);
// Returns an error string from the last exception (and clears it)
bool PyGetError(qstring *out = NULL);
// If an error occured (it calls PyGetError) it displays it and return TRUE
bool PyShowErr(const char *cb_name);
// [De]Initializes PyWraps
bool init_pywraps();
void deinit_pywraps();
// Returns the string representation of a PyObject
bool PyObjectToString(PyObject *obj, qstring *out);
// 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,
// Utility function to create a class instance whose constructor takes zero arguments
PyObject *create_idaapi_class_instance0(const char *clsname);
// Utility function to create linked class instances
PyObject *create_idaapi_linked_class_instance(const char *clsname, void *lnk);
// [De]Initializes PyWraps
bool init_pywraps();
void deinit_pywraps();
// Returns the string representation of a PyObject
bool PyObjectToString(PyObject *obj, qstring *out);
// Utility function to convert a python object to an IDC object
// and sets a python exception on failure.
bool convert_pyobj_to_idc_exc(PyObject *py_obj, idc_value_t *idc_obj);
// 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);
// 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

View File

@ -61,9 +61,17 @@
%ignore term_flags;
%ignore reset_flags;
%ignore flush_flags;
// TODO: These could be fixed if someone needs them.
%ignore data_type_t;
%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;
// TODO: This could be fixed (if needed)
%ignore set_dbgmem_source;
%include "bytes.hpp"
@ -76,6 +84,12 @@
%rename (nextthat) py_nextthat;
%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;
%{
@ -95,10 +109,505 @@ static bool idaapi py_testf_cb(flags_t flags, void *ud)
// Wraps the (next|prev)that()
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 (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)>
%}
@ -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;
// Allocate memory
char *buf = (char *) qalloc(size);
if (buf == NULL)
// Allocate memory via Python
PyObject *py_buf = PyString_FromStringAndSize(NULL, Py_ssize_t(size));
if ( py_buf == NULL )
break;
// 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
PyObject *py_buf;
if (ok)
py_buf = PyString_FromStringAndSize(buf, size);
// If failed, dispose the Python string
if ( !ok )
{
Py_DECREF(py_buf);
// Free buffer
qfree(buf);
// Return buffer to Python
if (ok)
return py_buf;
} while (false);
py_buf = Py_None;
Py_INCREF(py_buf);
}
return py_buf;
} while ( false );
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)>
%}
%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
typedef struct
{
ulonglong ival; // 8: integer value
ushort fval[6]; // 12: floating point value in the internal representation (see ieee.h)
} regval_t;
%ignore dbg;
%ignore get_manual_regions;
%rename (get_manual_regions) py_get_manual_regions;
%ignore set_manual_regions;
%include "dbg.hpp"
%ignore DBG_Callback;
%feature("director") DBG_Hooks;
%{
//<code(py_dbg)>
static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas);
//</code(py_dbg)>
%}
%inline %{
//<inline(py_dbg)>
//-------------------------------------------------------------------------
static PyObject *py_get_manual_regions()
{
meminfo_vec_t areas;
get_manual_regions(&areas);
return meminfo_vec_t_to_py(areas);
}
//-------------------------------------------------------------------------
static PyObject *refresh_debugger_memory()
{
invalidate_dbgmem_config();
invalidate_dbgmem_contents(BADADDR, BADADDR);
if ( dbg != NULL && dbg->stopped_at_debug_event != NULL )
dbg->stopped_at_debug_event(true);
Py_RETURN_NONE;
}
//</inline(py_dbg)>
int idaapi DBG_Callback(void *ud, int notification_code, va_list va);
class DBG_Hooks
{
public:
virtual ~DBG_Hooks() {};
bool hook() { return hook_to_notification_point(HT_DBG, DBG_Callback, this); };
bool unhook() { return unhook_from_notification_point(HT_DBG, DBG_Callback, this); };
/* Hook functions to be overridden in Python */
virtual void dbg_process_start(pid_t pid,
thid_t tid,
ea_t ea,
char *name,
ea_t base,
asize_t size) { };
virtual void dbg_process_exit(pid_t pid,
thid_t tid,
ea_t ea,
int exit_code) { };
virtual void dbg_process_attach(pid_t pid,
thid_t tid,
ea_t ea,
char *name,
ea_t base,
asize_t size) { };
virtual void dbg_process_detach(pid_t pid,
thid_t tid,
ea_t ea) { };
virtual void dbg_thread_start(pid_t pid,
thid_t tid,
ea_t ea) { };
virtual void dbg_thread_exit(pid_t pid,
thid_t tid,
ea_t ea,
int exit_code) { };
virtual void dbg_library_load(pid_t pid,
thid_t tid,
ea_t ea,
char *name,
ea_t base,
asize_t size) { };
virtual void dbg_library_unload(pid_t pid,
thid_t tid,
ea_t ea,
char *libname) { };
virtual void dbg_information(pid_t pid,
thid_t tid,
ea_t ea,
char *info) { };
virtual int dbg_exception(pid_t pid,
thid_t tid,
ea_t ea,
int code,
bool can_cont,
ea_t exc_ea,
char *info) { return 0; };
virtual void dbg_suspend_process(void) { };
virtual int dbg_bpt(thid_t tid, ea_t breakpoint_ea) { return 0; };
virtual int dbg_trace(thid_t tid, ea_t ip) { return 0; };
virtual void dbg_request_error(int failed_command,
int failed_dbg_notification) { };
virtual void dbg_step_into(void) { };
virtual void dbg_step_over(void) { };
virtual void dbg_run_to(thid_t tid) { };
virtual void dbg_step_until_ret(void) { };
};
int idaapi DBG_Callback(void *ud, int notification_code, va_list va)
{
class DBG_Hooks *proxy = (class DBG_Hooks *)ud;
debug_event_t *event;
thid_t tid;
int *warn;
ea_t ip;
ea_t breakpoint_ea;
try {
switch (notification_code)
{
case dbg_process_start:
event = va_arg(va, debug_event_t *);
proxy->dbg_process_start(event->pid,
event->tid,
event->ea,
event->modinfo.name,
event->modinfo.base,
event->modinfo.size);
return 0;
case dbg_process_exit:
event = va_arg(va, debug_event_t *);
proxy->dbg_process_exit(event->pid,
event->tid,
event->ea,
event->exit_code);
return 0;
case dbg_process_attach:
event = va_arg(va, debug_event_t *);
proxy->dbg_process_attach(event->pid,
event->tid,
event->ea,
event->modinfo.name,
event->modinfo.base,
event->modinfo.size);
return 0;
case dbg_process_detach:
event = va_arg(va, debug_event_t *);
proxy->dbg_process_detach(event->pid,
event->tid,
event->ea);
return 0;
case dbg_thread_start:
event = va_arg(va, debug_event_t *);
proxy->dbg_thread_start(event->pid,
event->tid,
event->ea);
return 0;
case dbg_thread_exit:
event = va_arg(va, debug_event_t *);
proxy->dbg_thread_exit(event->pid,
event->tid,
event->ea,
event->exit_code);
return 0;
case dbg_library_load:
event = va_arg(va, debug_event_t *);
proxy->dbg_library_load(event->pid,
event->tid,
event->ea,
event->modinfo.name,
event->modinfo.base,
event->modinfo.size);
return 0;
case dbg_library_unload:
event = va_arg(va, debug_event_t *);
proxy->dbg_library_unload(event->pid,
event->tid,
event->ea,
event->info);
return 0;
case dbg_information:
event = va_arg(va, debug_event_t *);
proxy->dbg_information(event->pid,
event->tid,
event->ea,
event->info);
return 0;
case dbg_exception:
event = va_arg(va, debug_event_t *);
warn = va_arg(va, int *);
*warn = proxy->dbg_exception(event->pid,
event->tid,
event->ea,
event->exc.code,
event->exc.can_cont,
event->exc.ea,
event->exc.info);
return 0;
case dbg_suspend_process:
proxy->dbg_suspend_process();
return 0;
case dbg_bpt:
tid = va_arg(va, thid_t);
breakpoint_ea = va_arg(va, ea_t);
warn = va_arg(va, int *);
*warn = proxy->dbg_bpt(tid, breakpoint_ea);
return 0;
case dbg_trace:
tid = va_arg(va, thid_t);
ip = va_arg(va, ea_t);
return proxy->dbg_bpt(tid, ip);
case dbg_request_error:
{
int failed_command = (int)va_arg(va, ui_notification_t);
int failed_dbg_notification = (int)va_arg(va, dbg_notification_t);
proxy->dbg_request_error(failed_command, failed_dbg_notification);
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;
}
%}
// SWIG chokes on the original declaration so it is replicated here
typedef struct
{
ulonglong ival; // 8: integer value
ushort fval[6]; // 12: floating point value in the internal representation (see ieee.h)
} regval_t;
%ignore dbg;
%ignore get_manual_regions;
%ignore source_file_t;
%ignore source_item_t;
%ignore srcinfo_provider_t;
%rename (get_manual_regions) py_get_manual_regions;
%ignore set_manual_regions;
%include "dbg.hpp"
%ignore DBG_Callback;
%feature("director") DBG_Hooks;
%{
//<code(py_dbg)>
static PyObject *meminfo_vec_t_to_py(meminfo_vec_t &areas);
//</code(py_dbg)>
%}
%inline %{
//<inline(py_dbg)>
//-------------------------------------------------------------------------
/*
#<pydoc>
def get_manual_regions():
"""
Returns the manual memory regions
@return: list(startEA, endEA, name, sclass, sbase, bitness, perm)
"""
pass
#</pydoc>
*/
static PyObject *py_get_manual_regions()
{
meminfo_vec_t areas;
get_manual_regions(&areas);
return meminfo_vec_t_to_py(areas);
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def refresh_debugger_memory():
"""
Refreshes the debugger memory
@return: Nothing
"""
pass
#</pydoc>
*/
static PyObject *refresh_debugger_memory()
{
invalidate_dbgmem_config();
invalidate_dbgmem_contents(BADADDR, 0);
if ( dbg != NULL && dbg->stopped_at_debug_event != NULL )
dbg->stopped_at_debug_event(true);
isEnabled(0);
Py_RETURN_NONE;
}
//</inline(py_dbg)>
int idaapi DBG_Callback(void *ud, int notification_code, va_list va);
class DBG_Hooks
{
public:
virtual ~DBG_Hooks() {};
bool hook() { return hook_to_notification_point(HT_DBG, DBG_Callback, this); };
bool unhook() { return unhook_from_notification_point(HT_DBG, DBG_Callback, this); };
/* Hook functions to be overridden in Python */
virtual void dbg_process_start(pid_t pid,
thid_t tid,
ea_t ea,
char *name,
ea_t base,
asize_t size) { };
virtual void dbg_process_exit(pid_t pid,
thid_t tid,
ea_t ea,
int exit_code) { };
virtual void dbg_process_attach(pid_t pid,
thid_t tid,
ea_t ea,
char *name,
ea_t base,
asize_t size) { };
virtual void dbg_process_detach(pid_t pid,
thid_t tid,
ea_t ea) { };
virtual void dbg_thread_start(pid_t pid,
thid_t tid,
ea_t ea) { };
virtual void dbg_thread_exit(pid_t pid,
thid_t tid,
ea_t ea,
int exit_code) { };
virtual void dbg_library_load(pid_t pid,
thid_t tid,
ea_t ea,
char *name,
ea_t base,
asize_t size) { };
virtual void dbg_library_unload(pid_t pid,
thid_t tid,
ea_t ea,
char *libname) { };
virtual void dbg_information(pid_t pid,
thid_t tid,
ea_t ea,
char *info) { };
virtual int dbg_exception(pid_t pid,
thid_t tid,
ea_t ea,
int code,
bool can_cont,
ea_t exc_ea,
char *info) { return 0; };
virtual void dbg_suspend_process(void) { };
virtual int dbg_bpt(thid_t tid, ea_t breakpoint_ea) { return 0; };
virtual int dbg_trace(thid_t tid, ea_t ip) { return 0; };
virtual void dbg_request_error(int failed_command,
int failed_dbg_notification) { };
virtual void dbg_step_into(void) { };
virtual void dbg_step_over(void) { };
virtual void dbg_run_to(thid_t tid) { };
virtual void dbg_step_until_ret(void) { };
};
int idaapi DBG_Callback(void *ud, int notification_code, va_list va)
{
class DBG_Hooks *proxy = (class DBG_Hooks *)ud;
debug_event_t *event;
thid_t tid;
int *warn;
ea_t ip;
ea_t breakpoint_ea;
try {
switch (notification_code)
{
case dbg_process_start:
event = va_arg(va, debug_event_t *);
proxy->dbg_process_start(event->pid,
event->tid,
event->ea,
event->modinfo.name,
event->modinfo.base,
event->modinfo.size);
return 0;
case dbg_process_exit:
event = va_arg(va, debug_event_t *);
proxy->dbg_process_exit(event->pid,
event->tid,
event->ea,
event->exit_code);
return 0;
case dbg_process_attach:
event = va_arg(va, debug_event_t *);
proxy->dbg_process_attach(event->pid,
event->tid,
event->ea,
event->modinfo.name,
event->modinfo.base,
event->modinfo.size);
return 0;
case dbg_process_detach:
event = va_arg(va, debug_event_t *);
proxy->dbg_process_detach(event->pid,
event->tid,
event->ea);
return 0;
case dbg_thread_start:
event = va_arg(va, debug_event_t *);
proxy->dbg_thread_start(event->pid,
event->tid,
event->ea);
return 0;
case dbg_thread_exit:
event = va_arg(va, debug_event_t *);
proxy->dbg_thread_exit(event->pid,
event->tid,
event->ea,
event->exit_code);
return 0;
case dbg_library_load:
event = va_arg(va, debug_event_t *);
proxy->dbg_library_load(event->pid,
event->tid,
event->ea,
event->modinfo.name,
event->modinfo.base,
event->modinfo.size);
return 0;
case dbg_library_unload:
event = va_arg(va, debug_event_t *);
proxy->dbg_library_unload(event->pid,
event->tid,
event->ea,
event->info);
return 0;
case dbg_information:
event = va_arg(va, debug_event_t *);
proxy->dbg_information(event->pid,
event->tid,
event->ea,
event->info);
return 0;
case dbg_exception:
event = va_arg(va, debug_event_t *);
warn = va_arg(va, int *);
*warn = proxy->dbg_exception(event->pid,
event->tid,
event->ea,
event->exc.code,
event->exc.can_cont,
event->exc.ea,
event->exc.info);
return 0;
case dbg_suspend_process:
proxy->dbg_suspend_process();
return 0;
case dbg_bpt:
tid = va_arg(va, thid_t);
breakpoint_ea = va_arg(va, ea_t);
warn = va_arg(va, int *);
*warn = proxy->dbg_bpt(tid, breakpoint_ea);
return 0;
case dbg_trace:
tid = va_arg(va, thid_t);
ip = va_arg(va, ea_t);
return proxy->dbg_bpt(tid, ip);
case dbg_request_error:
{
int failed_command = (int)va_argi(va, ui_notification_t);
int failed_dbg_notification = (int)va_argi(va, dbg_notification_t);
proxy->dbg_request_error(failed_command, failed_dbg_notification);
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(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
{
private:
@ -126,17 +216,17 @@ public:
}
//--------------------------------------------------------------------------
PyObject *open(const char *filename, bool remote = false)
bool open(const char *filename, bool remote = false)
{
close();
li = open_linput(filename, remote);
if ( li == NULL )
Py_RETURN_FALSE;
return false;
// Save file name
fn = filename;
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);
if ( l == NULL )
Py_RETURN_FALSE;
return false;
close();
li = l;
fn = "<memory>";
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)
{
do
@ -349,6 +456,7 @@ PyObject *py_enumerate_files(PyObject *path, PyObject *fname, PyObject *callback
%pythoncode %{
#<pycode(py_diskio)>
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)
#</pycode(py_diskio)>
%}

View File

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

View File

@ -7,8 +7,20 @@
%ignore register_extlang;
%ignore IDCFuncs;
%ignore set_idc_func;
%ignore set_idc_func_ex;
%ignore VarLong;
%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 VarFloat;
%ignore VarFree;

View File

@ -1,5 +1,79 @@
%inline %{
//<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
{
private:
@ -71,16 +145,16 @@ public:
}
//--------------------------------------------------------------------------
PyObject *open(const char *filename, const char *mode)
bool open(const char *filename, const char *mode)
{
close();
fp = qfopen(filename, mode);
if ( fp == NULL )
Py_RETURN_FALSE;
return false;
// Save file name
fn = filename;
own = true;
Py_RETURN_TRUE;
return true;
}
//--------------------------------------------------------------------------

View File

@ -16,5 +16,15 @@
%ignore read_stkpnts;
%ignore write_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"

View File

@ -1,45 +1,51 @@
%cstring_bounded_output_none(char *buf, MAXSTR);
%cstring_bounded_output_none(char *optlibs, MAXSTR);
// FIXME: Are these really useful?
%ignore iterate_func_chunks;
%ignore get_idasgn_desc;
%ignore get_idasgn_header_by_short_name;
// Kernel-only & unexported symbols
%ignore del_regargs;
%ignore write_regargs;
%ignore find_regarg;
%ignore free_regarg;
%ignore determine_rtl;
%ignore init_signatures;
%ignore save_signatures;
%ignore term_signatures;
%ignore init_funcs;
%ignore save_funcs;
%ignore term_funcs;
%ignore move_funcs;
%ignore copy_noret_info;
%ignore recalc_func_noret_flag;
%ignore plan_for_noret_analysis;
%ignore invalidate_sp_analysis;
%ignore create_func_eas_array;
%ignore auto_add_func_tails;
%ignore read_tails;
%include "funcs.hpp"
%clear(char *buf);
%clear(char *optlibs);
%inline %{
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];
}
%}
%cstring_bounded_output_none(char *buf, MAXSTR);
%cstring_bounded_output_none(char *optlibs, MAXSTR);
// FIXME: Are these really useful?
%ignore iterate_func_chunks;
%ignore get_idasgn_desc;
%ignore get_idasgn_header_by_short_name;
// Kernel-only & unexported symbols
%ignore del_regargs;
%ignore write_regargs;
%ignore find_regarg;
%ignore free_regarg;
%ignore determine_rtl;
%ignore init_signatures;
%ignore save_signatures;
%ignore term_signatures;
%ignore init_funcs;
%ignore save_funcs;
%ignore term_funcs;
%ignore move_funcs;
%ignore copy_noret_info;
%ignore recalc_func_noret_flag;
%ignore plan_for_noret_analysis;
%ignore invalidate_sp_analysis;
%ignore create_func_eas_array;
%ignore auto_add_func_tails;
%ignore read_tails;
%include "funcs.hpp"
%clear(char *buf);
%clear(char *optlibs);
%inline %{
/*
#<pydoc>
def get_fchunk_referer(ea, idx):
pass
#</pydoc>
*/
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 gdl_graph_t::gen_gdl;
%ignore gdl_graph_t::gen_gdl;
%ignore gdl_graph_t::path;
%ignore gdl_graph_t::path_exists;
%ignore intmap_t::dstr;
%ignore intmap_t::print;
%ignore intseq_t::add_block;
%ignore intseq_t::add_unique;
%ignore intseq_t::del;
%ignore intseq_t::dstr;
%ignore intseq_t::print;
%ignore intseq_t::remove_block;
%ignore intset_t::dstr;
%ignore intset_t::print;
%ignore node_set_t::add;
%ignore node_set_t::extract;
%ignore node_set_t::intersect;
%ignore node_set_t::node_set_t;
%ignore node_set_t::sub;
%ignore qflow_chart_t::blocks;
%ignore flow_chart_t;
%ignore setup_graph_subsystem;
%ignore qbasic_block_t::succ;
%ignore qbasic_block_t::pred;
%include "gdl.hpp"
%extend qflow_chart_t
{
qbasic_block_t *__getitem__(int n)
{
return &(self->blocks[n]);
}
}
%pythoncode %{
#<pycode(py_gdl)>
# -----------------------------------------------------------------------
class BasicBlock:
def __init__(self, id, bb, f):
self._f = f
self.id = id
"""Basic block ID"""
self.startEA = bb.startEA
"""startEA of basic block"""
self.endEA = bb.endEA
"""endEA of basic block"""
self.type = self._f._q.calc_block_type(self.id)
"""Block type (check fc_block_type_t enum)"""
def preds(self):
"""
Iterates the predecessors list
"""
q = self._f._q
for i in xrange(0, self._f._q.npred(self.id)):
yield self._f[q.pred(self.id, i)]
def succs(self):
"""
Iterates the successors list
"""
q = self._f._q
for i in xrange(0, q.nsucc(self.id)):
yield self._f[q.succ(self.id, i)]
# -----------------------------------------------------------------------
class FlowChart:
"""
Flowchart class used to determine basic blocks
"""
def __init__(self, f=None, bounds=None, flags=0):
"""
Constructor
@param f: A func_t type, use get_func(ea) to get a reference
@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
"""
if (not f) and (not bounds or type(bounds) != types.TupleType):
raise Exception("Please specifiy either a function or start/end pair")
if not bounds:
bounds = (BADADDR, BADADDR)
# create the flowchart
self._q = qflow_chart_t("", f, bounds[0], bounds[1], flags)
self.size = self._q.size()
def refresh():
self._q.refresh()
self.size = self._q.size()
def __getitem__(self, index):
"""
Returns a basic block
@return: BasicBlock
"""
if index >= self.size:
raise StopIteration
return BasicBlock(index, self._q[index], self)
#</pycode(py_gdl)>
%}
%ignore cancellable_graph_t::check_cancel;
%ignore gdl_graph_t::gen_gdl;
%ignore gdl_graph_t::gen_gdl;
%ignore gdl_graph_t::path;
%ignore gdl_graph_t::path_exists;
%ignore gdl_graph_t::gen_dot;
%ignore intmap_t::dstr;
%ignore intmap_t::print;
%ignore intseq_t::add_block;
%ignore intseq_t::add_unique;
%ignore intseq_t::del;
%ignore intseq_t::dstr;
%ignore intseq_t::print;
%ignore intseq_t::remove_block;
%ignore intset_t::dstr;
%ignore intset_t::print;
%ignore node_set_t::add;
%ignore node_set_t::extract;
%ignore node_set_t::intersect;
%ignore node_set_t::node_set_t;
%ignore node_set_t::sub;
%ignore qflow_chart_t::blocks;
%ignore flow_chart_t;
%ignore default_graph_format;
%ignore setup_graph_subsystem;
%ignore qbasic_block_t::succ;
%ignore qbasic_block_t::pred;
%include "gdl.hpp"
%extend qflow_chart_t
{
qbasic_block_t *__getitem__(int n)
{
return &(self->blocks[n]);
}
}
%pythoncode %{
#<pycode(py_gdl)>
# -----------------------------------------------------------------------
class BasicBlock:
"""Basic block class. It is returned by the Flowchart class"""
def __init__(self, id, bb, f):
self._f = f
self.id = id
"""Basic block ID"""
self.startEA = bb.startEA
"""startEA of basic block"""
self.endEA = bb.endEA
"""endEA of basic block"""
self.type = self._f._q.calc_block_type(self.id)
"""Block type (check fc_block_type_t enum)"""
def preds(self):
"""
Iterates the predecessors list
"""
q = self._f._q
for i in xrange(0, self._f._q.npred(self.id)):
yield self._f[q.pred(self.id, i)]
def succs(self):
"""
Iterates the successors list
"""
q = self._f._q
for i in xrange(0, q.nsucc(self.id)):
yield self._f[q.succ(self.id, i)]
# -----------------------------------------------------------------------
class FlowChart:
"""
Flowchart class used to determine basic blocks.
Check ex_gdl_qflow_chart.py for sample usage.
"""
def __init__(self, f=None, bounds=None, flags=0):
"""
Constructor
@param f: A func_t type, use get_func(ea) to get a reference
@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
"""
if (not f) and (not bounds or type(bounds) != types.TupleType):
raise Exception("Please specifiy either a function or start/end pair")
if not bounds:
bounds = (BADADDR, BADADDR)
# create the flowchart
self._q = qflow_chart_t("", f, bounds[0], bounds[1], flags)
self.size = self._q.size()
def refresh():
self._q.refresh()
self.size = self._q.size()
def __getitem__(self, index):
"""
Returns a basic block
@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 dual_text_options_t;
%ignore idainfo::init;
%ignore idainfo::retrieve;
%ignore idainfo::read;
%ignore idainfo::write;
%ignore idainfo::align_short_demnames;
%ignore idainfo::align_strtype;
%ignore idainfo::align_long_demnames;
%ignore setflag(uchar &where,uchar bit,int value);
%ignore setflag(ushort &where,ushort bit,int value);
%ignore setflag(uint32 &where,uint32 bit,int value);
// Make idainfo::get_proc_name() work
%cstring_bounded_output(char *buf, 8);
%ignore BADADDR;
%ignore BADSEL;
%include "ida.hpp"
%clear(char *buf);
// Ignore kernel-only symbols
%ignore dual_text_options_t;
%ignore idainfo::init;
%ignore idainfo::retrieve;
%ignore idainfo::read;
%ignore idainfo::write;
%ignore idainfo::align_short_demnames;
%ignore idainfo::align_strtype;
%ignore idainfo::align_long_demnames;
%ignore setflag(uchar &where,uchar bit,int value);
%ignore setflag(ushort &where,ushort bit,int value);
%ignore setflag(uint32 &where,uint32 bit,int value);
// Make idainfo::get_proc_name() work
%cstring_bounded_output(char *buf, 8);
%ignore BADADDR;
%ignore BADSEL;
%include "ida.hpp"
%clear(char *buf);

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
%ignore memory_info_t;
%ignore register_info_t;
%ignore appcall;
%ignore gdecode_t;
%apply unsigned char { char dtyp };
%include "idd.hpp"
@ -16,7 +17,7 @@ static bool dbg_can_query()
{
// Reject the request only if no debugger is set
// 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;
}
//-------------------------------------------------------------------------
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(
ea_t func_ea,
@ -202,7 +93,7 @@ PyObject *py_appcall(
msg("input variables:\n"
"----------------\n");
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]);
msg("%d]\n%s\n-----------\n", int(i), s.c_str());
@ -220,10 +111,10 @@ PyObject *py_appcall(
idc_args.begin(),
&idc_result);
if (ret != eOk)
if ( ret != eOk )
{
// An exception was thrown?
if (ret == eExecThrow)
if ( ret == eExecThrow )
{
// Convert the result (which is a debug_event) into a Python object
PyObject *py_appcall_exc(NULL);
@ -247,7 +138,7 @@ PyObject *py_appcall(
msg("return variables:\n"
"-----------------\n");
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]);
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
for (Py_ssize_t i=0;i<nargs;i++)
for ( Py_ssize_t i=0; i<nargs; i++ )
{
// Get argument
PyObject *py_item = PyList_GetItem(arg_list, i);
// We convert arguments but fail only on fatal errors
// (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");
return NULL;
@ -269,7 +160,7 @@ PyObject *py_appcall(
}
// Convert the result from IDC back to Python
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");
return NULL;
@ -293,11 +184,165 @@ PyObject *py_appcall(
%inline %{
//<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();
PyObject *dbg_get_memory_info();
//-------------------------------------------------------------------------
/*
#<pydoc>
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()
{
if ( dbg == NULL )
@ -305,6 +350,47 @@ static PyObject *dbg_get_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();
PyObject *py_appcall(
ea_t func_ea,
@ -368,15 +454,16 @@ bool can_exc_continue(const debug_event_t* ev)
import types
# -----------------------------------------------------------------------
# This class is used with |Appcall.array() method
class Appcall_array__(object):
"""This class is used with Appcall.array() method"""
def __init__(self, tp):
self.__type = tp
def pack(self, L):
"""Packs a list or tuple into a byref buffer"""
t = type(L)
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)
if self.__size == 1:
self.__typedobj = Appcall__.typedobj(self.__type + ";")
@ -390,6 +477,7 @@ class Appcall_array__(object):
return None
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))):
return obj
# 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)]
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
if isinstance(buf, PyIdc_cvt_refclass__):
buf = buf.value
@ -412,15 +501,6 @@ class Appcall_array__(object):
return 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()
@ -444,13 +524,29 @@ class Appcall_callable__(object):
self.__type = tp
self.__fields = fld
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):
return self.__options if self.__options != None else Appcall__.get_appcall_options()
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
"""Sets the Appcall options locally to this Appcall instance"""
options = property(__get_options, __set_options)
"""Sets the Appcall options locally to this Appcall instance"""
def __call__(self, *args):
"""Make object callable. We redirect execution to idaapi.appcall()"""
@ -475,7 +571,7 @@ class Appcall_callable__(object):
arg_list)
except Exception, e:
e_obj = e
# Restore appcall options
Appcall__.set_appcall_options(old_opt)
@ -488,8 +584,9 @@ class Appcall_callable__(object):
return self.__ea
def __set_ea(self, val):
self.__ea = val
"""Returns or sets the EA associated with this object"""
ea = property(__get_ea, __set_ea)
"""Returns or sets the EA associated with this object"""
def __get_size(self):
if self.__type == None:
@ -498,18 +595,20 @@ class Appcall_callable__(object):
if not r:
return -1
return r
"""Returns the size of the type"""
size = property(__get_size)
"""Returns the size of the type"""
def __get_type(self):
return self.__type
"""Returns the typestring"""
type = property(__get_type)
"""Returns the typestring"""
def __get_fields(self):
return self.__fields
"""Returns the typestring"""
fields = property(__get_fields)
"""Returns the field names"""
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.
@return: - 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)
@return:
- 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
@ -543,6 +643,8 @@ class Appcall_callable__(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):
self.__default = default
@ -551,26 +653,34 @@ class Appcall_consts__(object):
# -----------------------------------------------------------------------
class Appcall__(object):
APPCALL_MANUAL = 0x1
"""
Only set up the appcall, do not run it.
you should call CleanupAppcall() when finished
"""
APPCALL_MANUAL = 0x1
APPCALL_DEBEV = 0x2
"""
Return debug event information
If this bit is set, exceptions during appcall
will generate idc exceptions with full
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):
self.__consts = Appcall_consts__()
def __get_consts(self):
return self.__consts
"""Use Appcall.Consts.CONST_NAME to access constants"""
Consts = property(__get_consts)
"""Use Appcall.Consts.CONST_NAME to access constants"""
@staticmethod
def __name_or_ea(name_or_ea):
@ -591,7 +701,7 @@ class Appcall__(object):
@staticmethod
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
ea = Appcall__.__name_or_ea(name_or_ea)
@ -605,7 +715,7 @@ class Appcall__(object):
return Appcall_callable__(ea, result[1], result[2])
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
ea = self.__name_or_ea(name_or_ea)
if ea == _idaapi.BADADDR:
@ -663,7 +773,7 @@ class Appcall__(object):
@staticmethod
def obj(**kwds):
"""Returns an empty object or objects with attributes as passed via its keywords arguments"""
return Appcall_object__(**kwds)
return object_t(**kwds)
@staticmethod
def cstr(val):
@ -695,12 +805,14 @@ class Appcall__(object):
@staticmethod
def set_appcall_options(opt):
"""Method to change the Appcall options globally (not per Appcall)"""
old_opt = Appcall__.get_appcall_options()
_idaapi.cvar.inf.appcall_options = opt
return old_opt
@staticmethod
def get_appcall_options():
"""Return the global Appcall options"""
return _idaapi.cvar.inf.appcall_options
@staticmethod

View File

@ -1,339 +1,612 @@
// Ignore the following symbols
%ignore WorkReg;
%ignore AbstractRegister;
%ignore rginfo;
%ignore insn_t::get_canon_mnem;
%ignore insn_t::get_canon_feature;
%ignore insn_t::is_canon_insn;
%ignore bytes_t;
%ignore IDPOPT_STR;
%ignore IDPOPT_NUM;
%ignore IDPOPT_BIT;
%ignore IDPOPT_FLT;
%ignore IDPOPT_I64;
%ignore IDPOPT_OK;
%ignore IDPOPT_BADKEY;
%ignore IDPOPT_BADTYPE;
%ignore IDPOPT_BADVALUE;
%ignore set_options_t;
%ignore read_user_config_file;
%ignore s_preline;
%ignore ca_operation_t;
%ignore _chkarg_cmd;
%ignore ENUM_SIZE;
%ignore asm_t::checkarg_dispatch;
%ignore asm_t::func_header;
%ignore asm_t::func_footer;
%ignore asm_t::get_type_name;
%ignore instruc_t;
%ignore processor_t;
%ignore ph;
%ignore IDB_Callback;
%ignore free_processor_module;
%ignore read_config_file;
%ignore gen_idb_event;
%include "idp.hpp"
%feature("director") IDB_Hooks;
%inline %{
int idaapi IDB_Callback(void *ud, int notification_code, va_list va);
class IDB_Hooks
{
public:
virtual ~IDB_Hooks() {};
bool hook() { return hook_to_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 */
virtual int byte_patched(ea_t ea) { 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 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 enum_created(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_renamed(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_const_deleted(enum_t id, const_t cid) { 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_renamed(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_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_renamed(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 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 tail_owner_changed(func_t *tail, ea_t owner_func) { return 0; };
virtual int func_noret_changed(func_t *pfn) { return 0; };
virtual int segm_added(segment_t *s) { return 0; };
virtual int segm_deleted(ea_t startEA) { 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_moved(ea_t from, ea_t to, asize_t size) { return 0; };
};
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_const_created:
id = va_arg(va, enum_t);
cid = va_arg(va, const_t);
return proxy->enum_const_created(id, cid);
case idb_event::enum_const_deleted:
id = va_arg(va, enum_t);
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);
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;
}
// Assemble an instruction into the database (display a warning if an error is found)
// args:
// ea_t ea - linear address of instruction
// ea_t cs - cs of instruction
// ea_t ip - ip of instruction
// bool use32 - is 32bit segment?
// const char *line - line to assemble
// returns: 1: success, 0: failure
inline const int assemble(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
{
int inslen;
char buf[MAXSTR];
if (ph.notify != NULL)
{
inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf);
if (inslen > 0)
{
patch_many_bytes(ea, buf, inslen);
return 1;
}
}
return 0;
}
//<inline(py_idp)>
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// Assemble an instruction to a buffer (display a warning if an error is found)
// args:
// ea_t ea - linear address of instruction
// ea_t cs - cs of instruction
// ea_t ip - ip of instruction
// bool use32 - is 32bit segment?
// const char *line - line to assemble
// returns: 1: success, 0: failure
static PyObject *AssembleLine(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
{
int inslen;
char buf[MAXSTR];
if (ph.notify != NULL &&
(inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0)
{
return PyString_FromStringAndSize(buf, inslen);
}
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
static size_t ph_get_tbyte_size()
{
return ph.tbyte_size;
}
//-------------------------------------------------------------------------
static PyObject *ph_get_instruc()
{
Py_ssize_t i = 0;
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;
p != end;
++p )
{
PyTuple_SetItem(py_result, i++, Py_BuildValue("(sI)", p->name, p->feature));
}
return py_result;
}
//-------------------------------------------------------------------------
static PyObject *ph_get_regnames()
{
Py_ssize_t i = 0;
PyObject *py_result = PyList_New(ph.regsNum);
for ( Py_ssize_t i=0; i<ph.regsNum; i++ )
PyList_SetItem(py_result, i, PyString_FromString(ph.regNames[i]));
return py_result;
}
//</inline(py_idp)>
%}
// Ignore the following symbols
%ignore WorkReg;
%ignore AbstractRegister;
%ignore rginfo;
%ignore insn_t::get_canon_mnem;
%ignore insn_t::get_canon_feature;
%ignore insn_t::is_canon_insn;
%ignore bytes_t;
%ignore IDPOPT_STR;
%ignore IDPOPT_NUM;
%ignore IDPOPT_BIT;
%ignore IDPOPT_FLT;
%ignore IDPOPT_I64;
%ignore IDPOPT_OK;
%ignore IDPOPT_BADKEY;
%ignore IDPOPT_BADTYPE;
%ignore IDPOPT_BADVALUE;
%ignore set_options_t;
%ignore read_user_config_file;
%ignore s_preline;
%ignore ca_operation_t;
%ignore _chkarg_cmd;
%ignore ENUM_SIZE;
%ignore asm_t::checkarg_dispatch;
%ignore asm_t::func_header;
%ignore asm_t::func_footer;
%ignore asm_t::get_type_name;
%ignore instruc_t;
%ignore processor_t;
%ignore ph;
%ignore IDB_Callback;
%ignore IDP_Callback;
%ignore free_processor_module;
%ignore read_config_file;
%ignore gen_idb_event;
%include "idp.hpp"
%feature("director") IDB_Hooks;
%feature("director") IDP_Hooks;
%inline %{
int idaapi IDB_Callback(void *ud, int notification_code, va_list va);
class IDB_Hooks
{
public:
virtual ~IDB_Hooks() {};
bool hook() { return hook_to_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 */
virtual int byte_patched(ea_t ea) { 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 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 enum_created(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_renamed(enum_t id) { return 0; };
virtual int enum_cmt_changed(enum_t id) { return 0; };
virtual int enum_member_created(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_deleted(tid_t struc_id) { return 0; };
virtual int struc_renamed(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_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_renamed(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 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 tail_owner_changed(func_t *tail, ea_t owner_func) { return 0; };
virtual int func_noret_changed(func_t *pfn) { return 0; };
virtual int segm_added(segment_t *s) { return 0; };
virtual int segm_deleted(ea_t startEA) { 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_moved(ea_t from, ea_t to, asize_t size) { return 0; };
};
// Assemble an instruction into the database (display a warning if an error is found)
// args:
// ea_t ea - linear address of instruction
// ea_t cs - cs of instruction
// ea_t ip - ip of instruction
// bool use32 - is 32bit segment?
// const char *line - line to assemble
// returns: 1: success, 0: failure
inline const int assemble(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
{
int inslen;
char buf[MAXSTR];
if (ph.notify != NULL)
{
inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf);
if (inslen > 0)
{
patch_many_bytes(ea, buf, inslen);
return 1;
}
}
return 0;
}
//<inline(py_idp)>
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
/*
#<pydoc>
def AssembleLine(ea, cs, ip, use32, line):
"""
Assemble an instruction to a buffer (display a warning if an error is found)
@param ea: linear address of instruction
@param cs: cs of instruction
@param ip: ip of instruction
@param use32: is 32bit segment
@param line: line to assemble
@return:
- None on failure
- or a string containing the assembled instruction
"""
pass
#</pydoc>
*/
static PyObject *AssembleLine(ea_t ea, ea_t cs, ea_t ip, bool use32, const char *line)
{
int inslen;
char buf[MAXSTR];
if (ph.notify != NULL &&
(inslen = ph.notify(ph.assemble, ea, cs, ip, use32, line, buf)) > 0)
{
return PyString_FromStringAndSize(buf, inslen);
}
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def ph_get_tbyte_size():
"""
Returns the 'ph.tbyte_size' field as defined in he processor module
"""
pass
#</pydoc>
*/
static size_t ph_get_tbyte_size()
{
return ph.tbyte_size;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def ph_get_id():
"""
Returns the 'ph.id' field
"""
pass
#</pydoc>
*/
static size_t ph_get_id()
{
return ph.id;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def ph_get_instruc():
"""
Returns a list of tuples (instruction_name, instruction_feature) containing the
instructions list as defined in he processor module
"""
pass
#</pydoc>
*/
static PyObject *ph_get_instruc()
{
Py_ssize_t i = 0;
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;
p != end;
++p )
{
PyTuple_SetItem(py_result, i++, Py_BuildValue("(sI)", p->name, p->feature));
}
return py_result;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def ph_get_regnames():
"""
Returns the list of register names as defined in the processor module
"""
pass
#</pydoc>
*/
static PyObject *ph_get_regnames()
{
Py_ssize_t i = 0;
PyObject *py_result = PyList_New(ph.regsNum);
for ( Py_ssize_t i=0; i<ph.regsNum; i++ )
PyList_SetItem(py_result, i, PyString_FromString(ph.regNames[i]));
return py_result;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
class IDP_Hooks(object):
def custom_ana(self):
"""
Analyzes and decodes an instruction at idaapi.cmd.ea
- cmd.itype must be set >= idaapi.CUSTOM_CMD_ITYPE
- cmd.size must be set to the instruction length
@return: Boolean
- False if the instruction is not recognized
- True if the instruction was decoded. idaapi.cmd should be filled in that case.
"""
pass
def custom_out(self):
"""
Outputs the instruction defined in idaapi.cmd
@return: Boolean (whether this instruction can be outputted or not)
"""
pass
def custom_emu(self):
"""
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.
@return: Boolean (whether this instruction has been emulated or not)
"""
pass
def custom_outop(self, op):
"""
Notification to generate operand text.
If False was returned, then the standard operand output function will be called.
The output buffer is inited with init_output_buffer()
and this notification may use out_...() functions to form the operand text
@return: Boolean (whether the operand has been outputted or not)
"""
def custom_mnem(self):
"""
Prints the mnemonic of the instruction defined in idaapi.cmd
@return:
- None: No mnemonic. IDA will use the default mnemonic value if present
- String: The desired mnemonic string
"""
def is_sane_insn(self, no_crefs):
"""
is the instruction sane for the current file type?
@param no_crefs:
- 1: the instruction has no code refs to it.
ida just tries to convert unexplored bytes
to an instruction (but there is no other
reason to convert them into an instruction)
- 0: the instruction is created because
of some coderef, user request or another
weighty reason.
@return: 1-ok, <=0-no, the instruction isn't likely to appear in the program
"""
pass
def is_sane_insn(self, no_crefs):
"""
can a function start here?
@param state: autoanalysis phase
0: creating functions
1: creating chunks
@return: integer (probability 0..100)
"""
pass
#</pydoc>
*/
int idaapi IDP_Callback(void *ud, int notification_code, va_list va);
class IDP_Hooks
{
public:
virtual ~IDP_Hooks()
{
}
bool hook()
{
return hook_to_notification_point(HT_IDP, IDP_Callback, this);
}
bool unhook()
{
return unhook_from_notification_point(HT_IDP, IDP_Callback, this);
}
virtual bool custom_ana()
{
return false;
}
virtual bool custom_out()
{
return false;
}
virtual bool custom_emu()
{
return false;
}
virtual bool custom_outop(PyObject *py_op)
{
return false;
}
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
%ignore requires_color_esc;
%ignore tag_on;
%ignore tag_remove;
%ignore tag_off;
%ignore tag_addchr;
%ignore tag_addstr;
%ignore tag_addr;
%ignore tag_advance;
%ignore tag_skipcodes;
%ignore tag_skipcode;
%ignore set_user_defined_prefix;
%ignore get_user_defined_prefix;
// Ignore va_list versions
%ignore printf_line_v;
%ignore gen_colored_cmt_line_v;
%ignore gen_cmt_line_v;
%ignore add_long_cmt_v;
%ignore describex;
// Kernel-only and unexported symbols
%ignore init_sourcefiles;
%ignore save_sourcefiles;
%ignore term_sourcefiles;
%ignore move_sourcefiles;
%ignore gen_xref_lines;
%ignore ml_getcmt_t;
%ignore ml_getnam_t;
%ignore ml_genxrf_t;
%ignore ml_saver_t;
%ignore setup_makeline;
%ignore MAKELINE_NONE;
%ignore MAKELINE_BINPREF;
%ignore MAKELINE_VOID;
%ignore MAKELINE_STACK;
%ignore save_line_in_array;
%ignore init_lines_array;
%ignore finish_makeline;
%ignore generate_disassembly;
%ignore gen_labeled_line;
%ignore gen_lname_line;
%ignore makeline_producer_t;
%ignore set_makeline_producer;
%ignore closing_comment;
%ignore close_comment;
%ignore copy_extra_lines;
%ignore ExtraLines;
%ignore ExtraKill;
%ignore ExtraFree;
%ignore Dumper;
%ignore init_lines;
%ignore save_lines;
%ignore term_lines;
%ignore gl_namedone;
%ignore data_as_stack;
%ignore calc_stack_alignment;
%ignore align_down_to_stack;
%ignore align_up_to_stack;
%ignore remove_spaces;
%include "lines.hpp"
%rename (generate_disassembly) py_generate_disassembly;
%rename (tag_remove) py_tag_remove;
%rename (tag_addr) py_tag_addr;
%rename (tag_skipcodes) py_tag_skipcodes;
%rename (tag_skipcode) py_tag_skipcode;
%rename (tag_advance) py_tag_advance;
%rename (generate_disassembly) py_generate_disassembly;
%inline
{
//<inline(py_lines)>
//-------------------------------------------------------------------------
PyObject *py_tag_remove(const char *instr)
{
size_t sz = strlen(instr);
char *buf = new char[sz + 5];
if ( buf == NULL )
Py_RETURN_NONE;
ssize_t r = tag_remove(instr, buf, sz);
PyObject *res;
if ( r < 0 )
{
Py_INCREF(Py_None);
res = Py_None;
}
else
{
res = PyString_FromString(buf);
}
delete [] buf;
return res;
}
//-------------------------------------------------------------------------
PyObject *py_tag_addr(ea_t ea)
{
char buf[100];
tag_addr(buf, buf + sizeof(buf), ea);
return PyString_FromString(buf);
}
//-------------------------------------------------------------------------
int py_tag_skipcode(const char *line)
{
return tag_skipcode(line)-line;
}
//-------------------------------------------------------------------------
int py_tag_skipcodes(const char *line)
{
return tag_skipcodes(line)-line;
}
//-------------------------------------------------------------------------
int py_tag_advance(const char *line, int cnt)
{
return tag_advance(line, cnt)-line;
}
//-------------------------------------------------------------------------
PyObject *py_generate_disassembly(ea_t ea, int max_lines, bool as_stack, bool notags)
{
if ( max_lines <= 0 )
Py_RETURN_NONE;
qstring qbuf;
char **lines = new char *[max_lines];
int lnnum;
int nlines = generate_disassembly(ea, lines, max_lines, &lnnum, as_stack);
PyObject *py_tuple = PyTuple_New(nlines);
for ( int i=0; i<nlines; i++ )
{
const char *s = lines[i];
size_t line_len = strlen(s);
if ( notags )
{
qbuf.resize(line_len+5);
tag_remove(s, &qbuf[0], line_len);
s = (const char *)&qbuf[0];
}
PyTuple_SetItem(py_tuple, i, PyString_FromString(s));
qfree(lines[i]);
}
delete [] lines;
PyObject *py_result = Py_BuildValue("(iO)", lnnum, py_tuple);
Py_DECREF(py_tuple);
return py_result;
}
//</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):
return SCOLOR_ON + tag + str + SCOLOR_OFF + tag
#</pycode(py_lines)>
// FIXME: These should be fixed
%ignore requires_color_esc;
%ignore tag_on;
%ignore tag_remove;
%ignore tag_off;
%ignore tag_addchr;
%ignore tag_addstr;
%ignore tag_addr;
%ignore tag_advance;
%ignore tag_skipcodes;
%ignore tag_skipcode;
%ignore set_user_defined_prefix;
%ignore get_user_defined_prefix;
// Ignore va_list versions
%ignore printf_line_v;
%ignore gen_colored_cmt_line_v;
%ignore gen_cmt_line_v;
%ignore add_long_cmt_v;
%ignore describex;
// Kernel-only and unexported symbols
%ignore init_sourcefiles;
%ignore save_sourcefiles;
%ignore term_sourcefiles;
%ignore move_sourcefiles;
%ignore gen_xref_lines;
%ignore ml_getcmt_t;
%ignore ml_getnam_t;
%ignore ml_genxrf_t;
%ignore ml_saver_t;
%ignore setup_makeline;
%ignore MAKELINE_NONE;
%ignore MAKELINE_BINPREF;
%ignore MAKELINE_VOID;
%ignore MAKELINE_STACK;
%ignore save_line_in_array;
%ignore init_lines_array;
%ignore finish_makeline;
%ignore generate_disassembly;
%ignore gen_labeled_line;
%ignore gen_lname_line;
%ignore makeline_producer_t;
%ignore set_makeline_producer;
%ignore closing_comment;
%ignore close_comment;
%ignore copy_extra_lines;
%ignore ExtraLines;
%ignore ExtraKill;
%ignore ExtraFree;
%ignore Dumper;
%ignore init_lines;
%ignore save_lines;
%ignore term_lines;
%ignore gl_namedone;
%ignore data_as_stack;
%ignore calc_stack_alignment;
%ignore align_down_to_stack;
%ignore align_up_to_stack;
%ignore remove_spaces;
%ignore bgcolors;
%include "lines.hpp"
%rename (generate_disassembly) py_generate_disassembly;
%rename (tag_remove) py_tag_remove;
%rename (tag_addr) py_tag_addr;
%rename (tag_skipcodes) py_tag_skipcodes;
%rename (tag_skipcode) py_tag_skipcode;
%rename (tag_advance) py_tag_advance;
%rename (generate_disassembly) py_generate_disassembly;
%inline %{
//<inline(py_lines)>
//-------------------------------------------------------------------------
/*
#<pydoc>
def tag_remove(colstr):
"""
Remove color escape sequences from a string
@param colstr: the colored string with embedded tags
@return:
None on failure
or a new string w/o the tags
"""
pass
#</pydoc>
*/
PyObject *py_tag_remove(const char *instr)
{
size_t sz = strlen(instr);
char *buf = new char[sz + 5];
if ( buf == NULL )
Py_RETURN_NONE;
ssize_t r = tag_remove(instr, buf, sz);
PyObject *res;
if ( r < 0 )
{
Py_INCREF(Py_None);
res = Py_None;
}
else
{
res = PyString_FromString(buf);
}
delete [] buf;
return res;
}
//-------------------------------------------------------------------------
PyObject *py_tag_addr(ea_t ea)
{
char buf[100];
tag_addr(buf, buf + sizeof(buf), ea);
return PyString_FromString(buf);
}
//-------------------------------------------------------------------------
int py_tag_skipcode(const char *line)
{
return tag_skipcode(line)-line;
}
//-------------------------------------------------------------------------
int py_tag_skipcodes(const char *line)
{
return tag_skipcodes(line)-line;
}
//-------------------------------------------------------------------------
int py_tag_advance(const char *line, int cnt)
{
return tag_advance(line, cnt)-line;
}
//-------------------------------------------------------------------------
/*
#<pydoc>
def generate_disassembly(ea, max_lines, as_stack, notags):
"""
Generate disassembly lines (many lines) and put them into a buffer
@param ea: address to generate disassembly for
@param max_lines: how many lines max to generate
@param as_stack: Display undefined items as 2/4/8 bytes
@return:
- None on failure
- tuple(most_important_line_number, tuple(lines)) : Returns a tuple containing
the most important line number and a tuple of generated lines
"""
pass
#</pydoc>
*/
PyObject *py_generate_disassembly(
ea_t ea,
int max_lines,
bool as_stack,
bool notags)
{
if ( max_lines <= 0 )
Py_RETURN_NONE;
qstring qbuf;
char **lines = new char *[max_lines];
int lnnum;
int nlines = generate_disassembly(ea, lines, max_lines, &lnnum, as_stack);
PyObject *py_tuple = PyTuple_New(nlines);
for ( int i=0; i<nlines; i++ )
{
const char *s = lines[i];
size_t line_len = strlen(s);
if ( notags )
{
qbuf.resize(line_len+5);
tag_remove(s, &qbuf[0], line_len);
s = (const char *)&qbuf[0];
}
PyTuple_SetItem(py_tuple, i, PyString_FromString(s));
qfree(lines[i]);
}
delete [] lines;
PyObject *py_result = Py_BuildValue("(iO)", lnnum, py_tuple);
Py_DECREF(py_tuple);
return py_result;
}
//</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 add_fileregion;
%ignore move_fileregions;
%ignore del_fileregions;
%ignore local_gen_idc_file;
%ignore print_all_places;
%ignore save_text_line;
%ignore print_all_structs;
%ignore print_all_enums;
%ignore enum_processor_modules;
%ignore enum_plugins;
%ignore database_id0;
%ignore is_database_ext;
%ignore ida_database_memory;

View File

@ -45,13 +45,47 @@ static int idaapi py_import_enum_cb(
Py_XDECREF(py_result);
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)>
%}
%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(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];
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)
int py_enum_import_names(int mod_index, PyObject *py_cb)
/*
#<pydoc>
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) )
return -1;
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)>
%}
%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_supprev_idx8;
%ignore netnode_supdel_all;
%ignore netnode_supdel_range;
%ignore netnode_supdel_range_idx8;
%ignore netnode_hashval;
%ignore netnode_hashstr;
%ignore netnode_hashval_long;

View File

@ -1,5 +1,57 @@
%ignore wchar2char;
%ignore hit_counter_t;
%ignore print_all_counters;
%include "pro.h"
%ignore wchar2char;
%ignore hit_counter_t;
%ignore reg_hit_counter;
%ignore create_hit_counter;
%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 mark_rollback;
%ignore get_rollback_type;
%ignore mark_ida_decision;
%ignore unmark_ida_decision;
%ignore had_rolled_back;
%ignore ever_rolled_back;
%include "queue.hpp"

View File

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

View File

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

View File

@ -113,7 +113,10 @@
%ignore get_struct_member;
%ignore idb_type_to_til;
%ignore get_idb_type;
%ignore apply_type_to_stkarg;
%rename (apply_type_to_stkarg) py_apply_type_to_stkarg;
%ignore use_regarg_type_cb;
%ignore set_op_type_t;
%ignore is_stkarg_load_t;
@ -144,23 +147,6 @@
%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
%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;
qstring name;
bool ok = parse_decl(ti, decl, &name, &type, &fields, flags);
if (!ok)
if ( !ok )
Py_RETURN_NONE;
return Py_BuildValue("(sss)",
return Py_BuildValue("(sss)",
name.c_str(),
(char *)type.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)
{
if (!PyString_Check(tp))
if ( !PyString_Check(tp) )
{
PyErr_SetString(PyExc_ValueError, "String expected!");
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(
til_t *ti,
PyObject *py_type,
PyObject *py_fields,
ea_t ea,
int pio_flags)
int pio_flags = 0)
{
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(
til_t *ti,
PyObject *py_type,
PyObject *py_fields,
PyObject *py_bytes,
int pio_flags)
int pio_flags = 0)
{
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
// Returns the error_t returned by idasdk.pack_object_to_idb
/*
#<pydoc>
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_obj,
til_t *ti,
PyObject *py_type,
PyObject *py_fields,
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!");
return NULL;
@ -297,7 +336,7 @@ PyObject *py_pack_object_to_idb(
// Convert Python object to IDC object
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;
// 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)
PyObject *py_pack_object_to_bv(
PyObject *py_obj,
@ -319,7 +375,7 @@ PyObject *py_pack_object_to_bv(
ea_t base_ea,
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!");
return NULL;
@ -327,7 +383,7 @@ PyObject *py_pack_object_to_bv(
// Convert Python object to IDC object
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;
// Get type strings
@ -337,24 +393,24 @@ PyObject *py_pack_object_to_bv(
// Pack
relobj_t bytes;
error_t err = pack_object_to_bv(
&idc_obj,
ti,
type,
fields,
&bytes,
NULL,
&idc_obj,
ti,
type,
fields,
&bytes,
NULL,
pio_flags);
do
do
{
if (err != eOk)
if ( err != eOk )
break;
if (!bytes.relocate(base_ea, inf.mf))
if ( !bytes.relocate(base_ea, inf.mf) )
{
err = -1;
break;
}
return Py_BuildValue("(is#)", 1, bytes.begin(), bytes.size());
} while (false);
} while ( false );
return Py_BuildValue("(ii)", 0, err);
}
//</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_call_xref;
%ignore destroy_switch_info;
%ignore create_switch_xrefs;
%ignore create_switch_table;
// These functions should not be called directly (according to docs)
%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')