mirror of
https://github.com/cemu-project/idapython.git
synced 2024-12-24 16:51:52 +01:00
IDAPython 1.4.0 - IDA Pro 5.7 support
This commit is contained in:
parent
5f2262fad9
commit
3a5063330c
123
BUILDING.txt
123
BUILDING.txt
@ -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.
|
||||
|
222
CHANGES.txt
222
CHANGES.txt
@ -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
|
||||
|
||||
|
||||
|
54
COPYING.txt
54
COPYING.txt
@ -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.
|
||||
|
||||
|
||||
|
172
README.txt
172
README.txt
@ -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.
|
||||
|
||||
|
132
STATUS.txt
132
STATUS.txt
@ -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
|
||||
|
83
build.py
83
build.py
@ -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()
|
18
examples/ex_add_menu_item.py
Normal file
18
examples/ex_add_menu_item.py
Normal 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!"
|
@ -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
2435
python.cpp
File diff suppressed because it is too large
Load Diff
1113
python/idautils.py
1113
python/idautils.py
File diff suppressed because it is too large
Load Diff
15081
python/idc.py
15081
python/idc.py
File diff suppressed because it is too large
Load Diff
307
python/init.py
307
python/init.py
@ -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.
|
122
pywraps.hpp
122
pywraps.hpp
@ -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
|
960
swig/bytes.i
960
swig/bytes.i
@ -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)>
|
||||
%}
|
552
swig/dbg.i
552
swig/dbg.i
@ -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;
|
||||
}
|
||||
|
||||
%}
|
||||
|
120
swig/diskio.i
120
swig/diskio.i
@ -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)>
|
||||
%}
|
||||
|
58
swig/enum.i
58
swig/enum.i
@ -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"
|
||||
|
12
swig/expr.i
12
swig/expr.i
@ -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;
|
||||
|
80
swig/fpro.i
80
swig/fpro.i
@ -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;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
10
swig/frame.i
10
swig/frame.i
@ -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"
|
||||
|
96
swig/funcs.i
96
swig/funcs.i
@ -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];
|
||||
}
|
||||
%}
|
||||
|
207
swig/gdl.i
207
swig/gdl.i
@ -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)>
|
||||
%}
|
||||
|
1821
swig/graph.i
1821
swig/graph.i
File diff suppressed because it is too large
Load Diff
46
swig/ida.i
46
swig/ida.i
@ -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);
|
||||
|
3230
swig/idaapi.i
3230
swig/idaapi.i
File diff suppressed because it is too large
Load Diff
410
swig/idd.i
410
swig/idd.i
@ -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
|
||||
|
951
swig/idp.i
951
swig/idp.i
@ -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)>
|
||||
%}
|
4732
swig/kernwin.i
4732
swig/kernwin.i
File diff suppressed because it is too large
Load Diff
409
swig/lines.i
409
swig/lines.i
@ -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)>
|
||||
|
||||
%}
|
@ -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;
|
||||
|
612
swig/nalt.i
612
swig/nalt.i
@ -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)>
|
||||
%}
|
@ -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;
|
||||
|
62
swig/pro.i
62
swig/pro.i
@ -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"
|
||||
|
||||
|
@ -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"
|
@ -2,6 +2,7 @@
|
||||
%ignore createSRarea;
|
||||
%ignore killSRareas;
|
||||
%ignore delSRarea;
|
||||
%ignore splitSRarea;
|
||||
%ignore SRareaStart;
|
||||
%ignore SRareaEnd;
|
||||
%ignore repairSRarea;
|
||||
|
@ -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"
|
||||
|
140
swig/typeinf.i
140
swig/typeinf.i
@ -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)>
|
||||
|
@ -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
85
tools/swigdocs.py
Normal 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')
|
Loading…
Reference in New Issue
Block a user