mirror of
https://github.com/cemu-project/idapython.git
synced 2024-11-24 01:59:18 +01:00
- IDA Pro 6.3 support
- The Functions() generator function now accepts function tail start parameter - Added into idc.py: DbgRead/DbgWrite/SetTargetAssembler and stack pointer related functions - Wrapped more type info related functions
This commit is contained in:
parent
4d21b10dc4
commit
69d5c83d28
@ -1,5 +1,11 @@
|
||||
Please see http://code.google.com/p/idapython/source/list for a detailed list of changes.
|
||||
|
||||
Changes from version 1.5.4 to 1.5.5
|
||||
------------------------------------
|
||||
- IDA Pro 6.3 support
|
||||
- The Functions() generator function now accepts function tail start parameter
|
||||
- Added into idc.py: DbgRead/DbgWrite/SetTargetAssembler and stack pointer related functions
|
||||
- Wrapped more type info related functions
|
||||
|
||||
Changes from version 1.5.3 to 1.5.4
|
||||
------------------------------------
|
||||
|
15
build.py
15
build.py
@ -24,7 +24,7 @@ from distutils import sysconfig
|
||||
VERBOSE = True
|
||||
|
||||
IDA_MAJOR_VERSION = 6
|
||||
IDA_MINOR_VERSION = 2
|
||||
IDA_MINOR_VERSION = 3
|
||||
|
||||
if 'IDA' in os.environ:
|
||||
IDA_SDK = os.environ['IDA']
|
||||
@ -36,7 +36,7 @@ else:
|
||||
# IDAPython version
|
||||
VERSION_MAJOR = 1
|
||||
VERSION_MINOR = 5
|
||||
VERSION_PATCH = 4
|
||||
VERSION_PATCH = 5
|
||||
|
||||
# Determine Python version
|
||||
PYTHON_MAJOR_VERSION = int(platform.python_version()[0])
|
||||
@ -319,10 +319,11 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
||||
builder = GCCBuilder()
|
||||
platform_macros = [ "__LINUX__" ]
|
||||
python_libpath = os.path.join(sysconfig.EXEC_PREFIX, "lib")
|
||||
python_library = "-lpython%d.%d" % (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION)
|
||||
python_library = "-Bdynamic -lpython%d.%d" % (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION)
|
||||
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_linux_gcc_64" or "x86_linux_gcc_32")
|
||||
ida_lib = ""
|
||||
extra_link_parameters = ""
|
||||
extra_link_parameters = " -s"
|
||||
builder.compiler_parameters += " -O2"
|
||||
# Platform-specific settings for the Windows build
|
||||
elif platform == "win32":
|
||||
builder = MSVCBuilder()
|
||||
@ -333,6 +334,7 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
||||
ida_lib = "ida.lib"
|
||||
SWIG_OPTIONS += " -D__NT__ "
|
||||
extra_link_parameters = ""
|
||||
builder.compiler_parameters += " -Ox"
|
||||
# Platform-specific settings for the Mac OS X build
|
||||
elif platform == "macosx":
|
||||
builder = GCCBuilder()
|
||||
@ -342,7 +344,8 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
||||
python_library = "-framework Python"
|
||||
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_mac_gcc_64" or "x86_mac_gcc_32")
|
||||
ida_lib = ea64 and "-lida64" or "-lida"
|
||||
extra_link_parameters = ""
|
||||
extra_link_parameters = " -s"
|
||||
builder.compiler_parameters += " -O3"
|
||||
|
||||
assert builder, "Unknown platform! No idea how to build here..."
|
||||
|
||||
@ -350,6 +353,8 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
|
||||
if ea64:
|
||||
platform_macros.append("__EA64__")
|
||||
|
||||
platform_macros.append("NDEBUG")
|
||||
|
||||
if not '--no-early-load' in sys.argv:
|
||||
platform_macros.append("PLUGINFIX")
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to extend IDC from Python
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
from idaapi import set_idc_func_ex
|
||||
|
||||
#<pycode(ex_expr)>
|
||||
def py_power(n, e):
|
||||
return n ** e
|
||||
|
||||
ok = set_idc_func_ex("pow", py_power, (idaapi.VT_LONG, idaapi.VT_LONG), 0)
|
||||
if ok:
|
||||
print("Now the pow() will be present IDC!")
|
||||
else:
|
||||
print("Failed to register pow() IDC function")
|
||||
#</pycode(ex_expr)>
|
||||
# -----------------------------------------------------------------------
|
||||
# This is an example illustrating how to extend IDC from Python
|
||||
# (c) Hex-Rays
|
||||
#
|
||||
from idaapi import set_idc_func_ex
|
||||
|
||||
#<pycode(ex_expr)>
|
||||
def py_power(n, e):
|
||||
return n ** e
|
||||
|
||||
ok = set_idc_func_ex("pow", py_power, (idaapi.VT_LONG, idaapi.VT_LONG), 0)
|
||||
if ok:
|
||||
print("Now the pow() will be present IDC!")
|
||||
else:
|
||||
print("Failed to register pow() IDC function")
|
||||
#</pycode(ex_expr)>
|
||||
|
@ -8,3 +8,7 @@ REMOVE_CWD_SYS_PATH = 0
|
||||
// Script timeout (in seconds)
|
||||
// (A value of 0 disables the timeout)
|
||||
SCRIPT_TIMEOUT = 3
|
||||
|
||||
// Use a local Python library
|
||||
// If enabled, the "lib" directory tree with modules must be present in IDADIR/python
|
||||
USE_LOCAL_PYTHON = 0
|
||||
|
56
python.cpp
56
python.cpp
@ -125,6 +125,7 @@ static int script_timeout = 2;
|
||||
static bool g_ui_ready = false;
|
||||
static bool g_alert_auto_scripts = true;
|
||||
static bool g_remove_cwd_sys_path = false;
|
||||
static bool g_use_local_python = false;
|
||||
|
||||
static void end_execution();
|
||||
static void begin_execution();
|
||||
@ -369,6 +370,11 @@ const char *idaapi set_python_options(
|
||||
g_remove_cwd_sys_path = *(uval_t *)value != 0;
|
||||
break;
|
||||
}
|
||||
else if ( qstrcmp(keyword, "USE_LOCAL_PYTHON") == 0 )
|
||||
{
|
||||
g_use_local_python = *(uval_t *)value != 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return IDPOPT_BADKEY;
|
||||
} while (false);
|
||||
@ -466,7 +472,10 @@ static bool IDAPython_ExecFile(const char *FileName, char *errbuf, size_t errbuf
|
||||
{
|
||||
PyObject *py_execscript = get_idaapi_attr(S_IDAAPI_EXECSCRIPT);
|
||||
if ( py_execscript == NULL )
|
||||
{
|
||||
qstrncpy(errbuf, "Could not find idaapi." S_IDAAPI_EXECSCRIPT " ?!", errbufsz);
|
||||
return false;
|
||||
}
|
||||
|
||||
char script[MAXSTR];
|
||||
qstrncpy(script, FileName, sizeof(script));
|
||||
@ -1288,6 +1297,25 @@ static void sanitize_path()
|
||||
PySys_SetPath(newpath.begin());
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// we have to do it ourselves because Python 2.7 calls exit() if importing site fails
|
||||
static bool initsite(void)
|
||||
{
|
||||
PyObject *m;
|
||||
m = PyImport_ImportModule("site");
|
||||
if (m == NULL)
|
||||
{
|
||||
PyErr_Print();
|
||||
Py_Finalize();
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
Py_DECREF(m);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Initialize the Python environment
|
||||
bool IDAPython_Init(void)
|
||||
@ -1306,12 +1334,11 @@ bool IDAPython_Init(void)
|
||||
char tmp[QMAXPATH];
|
||||
#ifdef __LINUX__
|
||||
// Export symbols from libpython to resolve imported module deps
|
||||
qsnprintf(tmp, sizeof(tmp), "libpython%d.%d.so.1",
|
||||
PY_MAJOR_VERSION,
|
||||
PY_MINOR_VERSION);
|
||||
if ( !dlopen(tmp, RTLD_NOLOAD | RTLD_GLOBAL | RTLD_LAZY) )
|
||||
// use the standard soname: libpython2.7.so.1.0
|
||||
#define PYLIB "libpython" QSTRINGIZE(PY_MAJOR_VERSION) "." QSTRINGIZE(PY_MINOR_VERSION) ".so.1.0"
|
||||
if ( !dlopen(PYLIB, RTLD_NOLOAD | RTLD_GLOBAL | RTLD_LAZY) )
|
||||
{
|
||||
warning("IDAPython: %s", dlerror());
|
||||
warning("IDAPython dlopen(" PYLIB ") error: %s", dlerror());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@ -1350,16 +1377,31 @@ bool IDAPython_Init(void)
|
||||
}
|
||||
}
|
||||
|
||||
if ( g_use_local_python )
|
||||
Py_SetPythonHome(g_idapython_dir);
|
||||
|
||||
// don't import "site" right now
|
||||
Py_NoSiteFlag = 1;
|
||||
|
||||
// Start the interpreter
|
||||
Py_Initialize();
|
||||
|
||||
if ( !Py_IsInitialized() )
|
||||
{
|
||||
warning("IDAPython: Py_Initialize() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove current directory
|
||||
sanitize_path();
|
||||
|
||||
// import "site"
|
||||
if ( !g_use_local_python && !initsite() )
|
||||
{
|
||||
warning("IDAPython: importing \"site\" failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enable multi-threading support
|
||||
if ( !PyEval_ThreadsInitialized() )
|
||||
PyEval_InitThreads();
|
||||
@ -1416,7 +1458,7 @@ bool IDAPython_Init(void)
|
||||
parse_plugin_options();
|
||||
|
||||
// Register a RunPythonStatement() function for IDC
|
||||
set_idc_func(S_IDC_RUNPYTHON_STATEMENT, idc_runpythonstatement, idc_runpythonstatement_args);
|
||||
set_idc_func_ex(S_IDC_RUNPYTHON_STATEMENT, idc_runpythonstatement, idc_runpythonstatement_args, 0);
|
||||
|
||||
// A script specified on the command line is run
|
||||
if ( g_run_when == run_on_init )
|
||||
@ -1463,7 +1505,7 @@ void IDAPython_Term(void)
|
||||
deinit_pywraps();
|
||||
|
||||
// Uninstall IDC function
|
||||
set_idc_func(S_IDC_RUNPYTHON_STATEMENT, NULL, NULL);
|
||||
set_idc_func_ex(S_IDC_RUNPYTHON_STATEMENT, NULL, NULL, 0);
|
||||
|
||||
// Shut the interpreter down
|
||||
Py_Finalize();
|
||||
|
@ -217,9 +217,14 @@ def Functions(start=None, end=None):
|
||||
if not start: start = idaapi.cvar.inf.minEA
|
||||
if not end: end = idaapi.cvar.inf.maxEA
|
||||
|
||||
func = idaapi.get_func(start)
|
||||
if not func:
|
||||
func = idaapi.get_next_func(start)
|
||||
# find first function head chunk in the range
|
||||
chunk = idaapi.get_fchunk(start)
|
||||
if not chunk:
|
||||
chunk = idaapi.get_next_fchunk(start)
|
||||
while chunk and chunk.startEA < end and (chunk.flags & idaapi.FUNC_TAIL) != 0:
|
||||
chunk = idaapi.get_next_fchunk(chunk.startEA)
|
||||
func = chunk
|
||||
|
||||
while func and func.startEA < end:
|
||||
startea = func.startEA
|
||||
yield startea
|
||||
|
210
python/idc.py
210
python/idc.py
@ -1772,6 +1772,35 @@ def DbgQword(ea):
|
||||
return __DbgValue(ea, 8)
|
||||
|
||||
|
||||
def DbgRead(ea, size):
|
||||
"""
|
||||
Read from debugger memory.
|
||||
|
||||
@param ea: linear address
|
||||
@param size: size of data to read
|
||||
@return: data as a string. If failed, If failed, throws an exception
|
||||
|
||||
Thread-safe function (may be called only from the main thread and debthread)
|
||||
"""
|
||||
return idaapi.dbg_read_memory(ea, size)
|
||||
|
||||
|
||||
def DbgWrite(ea, data):
|
||||
"""
|
||||
Write to debugger memory.
|
||||
|
||||
@param ea: linear address
|
||||
@param data: string to write
|
||||
@return: number of written bytes (-1 - network/debugger error)
|
||||
|
||||
Thread-safe function (may be called only from the main thread and debthread)
|
||||
"""
|
||||
if not idaapi.dbg_can_query():
|
||||
return -1
|
||||
elif len(data) > 0:
|
||||
return idaapi.dbg_write_memory(ea, data)
|
||||
|
||||
|
||||
def GetOriginalByte(ea):
|
||||
"""
|
||||
Get original value of program byte
|
||||
@ -2867,6 +2896,16 @@ def SetProcessorType (processor, level):
|
||||
"""
|
||||
return idaapi.set_processor_type(processor, level)
|
||||
|
||||
def SetTargetAssembler(asmidx):
|
||||
"""
|
||||
Set target assembler
|
||||
@param asmidx: index of the target assembler in the array of
|
||||
assemblers for the current processor.
|
||||
|
||||
@return: 1-ok, 0-failed
|
||||
"""
|
||||
return idaapi.set_target_assembler(asmidx)
|
||||
|
||||
SETPROC_COMPAT = idaapi.SETPROC_COMPAT
|
||||
SETPROC_ALL = idaapi.SETPROC_ALL
|
||||
SETPROC_USER = idaapi.SETPROC_USER
|
||||
@ -4340,6 +4379,75 @@ def SetSpDiff(ea, delta):
|
||||
return idaapi.add_user_stkpnt(ea, delta)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# S T A C K
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
def AddAutoStkPnt2(func_ea, ea, delta):
|
||||
"""
|
||||
Add automatical SP register change point
|
||||
@param func_ea: function start
|
||||
@param ea: linear address where SP changes
|
||||
usually this is the end of the instruction which
|
||||
modifies the stack pointer (cmd.ea+cmd.size)
|
||||
@param delta: difference between old and new values of SP
|
||||
@return: 1-ok, 0-failed
|
||||
"""
|
||||
pfn = idaapi.get_func(func_ea)
|
||||
if not pfn:
|
||||
return 0
|
||||
return idaapi.add_auto_stkpnt2(pfn, ea, delta)
|
||||
|
||||
def AddUserStkPnt(ea, delta):
|
||||
"""
|
||||
Add user-defined SP register change point.
|
||||
|
||||
@param ea: linear address where SP changes
|
||||
@param delta: difference between old and new values of SP
|
||||
|
||||
@return: 1-ok, 0-failed
|
||||
"""
|
||||
return idaapi.add_user_stkpnt(ea, delta);
|
||||
|
||||
def DelStkPnt(func_ea, ea):
|
||||
"""
|
||||
Delete SP register change point
|
||||
|
||||
@param func_ea: function start
|
||||
@param ea: linear address
|
||||
@return: 1-ok, 0-failed
|
||||
"""
|
||||
pfn = idaapi.get_func(func_ea)
|
||||
if not pfn:
|
||||
return 0
|
||||
return idaapi.del_stkpnt(pfn, ea)
|
||||
|
||||
def GetMinSpd(func_ea):
|
||||
"""
|
||||
Return the address with the minimal spd (stack pointer delta)
|
||||
If there are no SP change points, then return BADADDR.
|
||||
|
||||
@param func_ea: function start
|
||||
@return: BADDADDR - no such function
|
||||
"""
|
||||
pfn = idaapi.get_func(func_ea)
|
||||
if not pfn:
|
||||
return BADADDR
|
||||
return idaapi.get_min_spd_ea(pfn)
|
||||
|
||||
def RecalcSpd(cur_ea):
|
||||
"""
|
||||
Recalculate SP delta for an instruction that stops execution.
|
||||
|
||||
@param cur_ea: linear address of the current instruction
|
||||
@return: 1 - new stkpnt is added, 0 - nothing is changed
|
||||
"""
|
||||
return idaapi.recalc_spd(cur_ea)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# E N T R Y P O I N T S
|
||||
# ----------------------------------------------------------------------------
|
||||
@ -4458,9 +4566,9 @@ def GetFixupTgtType(ea):
|
||||
@return: -1 - no fixup at the specified address
|
||||
otherwise returns fixup target type:
|
||||
"""
|
||||
fd = idaapi.get_fixup(ea)
|
||||
fd = idaapi.fixup_data_t()
|
||||
|
||||
if not fd:
|
||||
if not idaapi.get_fixup(ea, fd):
|
||||
return -1
|
||||
|
||||
return fd.type
|
||||
@ -4504,8 +4612,12 @@ def GetFixupTgtSel(ea):
|
||||
@return: -1 - no fixup at the specified address
|
||||
otherwise returns fixup target selector
|
||||
"""
|
||||
fd = idaapi.get_fixup(ea)
|
||||
return -1 if not fd else fd.sel
|
||||
fd = idaapi.fixup_data_t()
|
||||
|
||||
if not idaapi.get_fixup(ea, fd):
|
||||
return -1
|
||||
|
||||
return fd.sel
|
||||
|
||||
|
||||
def GetFixupTgtOff(ea):
|
||||
@ -4517,8 +4629,12 @@ def GetFixupTgtOff(ea):
|
||||
@return: -1 - no fixup at the specified address
|
||||
otherwise returns fixup target offset
|
||||
"""
|
||||
fd = idaapi.get_fixup(ea)
|
||||
return -1 if not fd else fd.off
|
||||
fd = idaapi.fixup_data_t()
|
||||
|
||||
if not idaapi.get_fixup(ea, fd):
|
||||
return -1
|
||||
|
||||
return fd.off
|
||||
|
||||
|
||||
def GetFixupTgtDispl(ea):
|
||||
@ -4530,8 +4646,12 @@ def GetFixupTgtDispl(ea):
|
||||
@return: -1 - no fixup at the specified address
|
||||
otherwise returns fixup target displacement
|
||||
"""
|
||||
fd = idaapi.get_fixup(ea)
|
||||
return -1 if not fd else fd.displacement
|
||||
fd = idaapi.fixup_data_t()
|
||||
|
||||
if not idaapi.get_fixup(ea, fd):
|
||||
return -1
|
||||
|
||||
return fd.displacement
|
||||
|
||||
|
||||
def SetFixup(ea, fixuptype, targetsel, targetoff, displ):
|
||||
@ -4791,6 +4911,30 @@ def GetMemberQty(sid):
|
||||
return -1 if not s else s.memqty
|
||||
|
||||
|
||||
def GetMemberId(sid, member_offset):
|
||||
"""
|
||||
@param sid: structure type ID
|
||||
@param member_offset:. The offset can be
|
||||
any offset in the member. For example,
|
||||
is a member is 4 bytes long and starts
|
||||
at offset 2, then 2,3,4,5 denote
|
||||
the same structure member.
|
||||
|
||||
@return: -1 if bad structure type ID is passed or there is
|
||||
no member at the specified offset.
|
||||
otherwise returns the member id.
|
||||
"""
|
||||
s = idaapi.get_struc(sid)
|
||||
if not s:
|
||||
return -1
|
||||
|
||||
m = idaapi.get_member(s, member_offset)
|
||||
if not m:
|
||||
return -1
|
||||
|
||||
return m.id
|
||||
|
||||
|
||||
def GetStrucPrevOff(sid, offset):
|
||||
"""
|
||||
Get previous offset in a structure
|
||||
@ -6633,6 +6777,15 @@ def SizeOf(typestr):
|
||||
"""
|
||||
return idaapi.get_type_size0(idaapi.cvar.idati, typestr)
|
||||
|
||||
def GetTinfo(ea):
|
||||
"""
|
||||
Get type information of function/variable as 'typeinfo' object
|
||||
|
||||
@param ea: the address of the object
|
||||
@return: None on failure, or (type, fields) tuple.
|
||||
"""
|
||||
return idaapi.idc_get_type_raw(ea)
|
||||
|
||||
def GuessType(ea):
|
||||
"""
|
||||
Guess type of function/variable
|
||||
@ -6652,11 +6805,16 @@ def SetType(ea, newtype):
|
||||
@param newtype: the type string in C declaration form.
|
||||
Must contain the closing ';'
|
||||
if specified as an empty string, then the
|
||||
assciated with 'ea' will be deleted
|
||||
item associated with 'ea' will be deleted.
|
||||
|
||||
@return: 1-ok, 0-failed.
|
||||
"""
|
||||
return idaapi.apply_cdecl2(idaapi.cvar.idati, ea, newtype)
|
||||
if newtype is not '':
|
||||
return idaapi.apply_cdecl2(idaapi.cvar.idati, ea, newtype)
|
||||
if idaapi.has_ti(ea):
|
||||
idaapi.del_tinfo(ea)
|
||||
return True
|
||||
return False
|
||||
|
||||
def ParseType(inputtype, flags):
|
||||
"""
|
||||
@ -7680,6 +7838,29 @@ def SetBptAttr(address, bptattr, value):
|
||||
idaapi.update_bpt(bpt)
|
||||
return True
|
||||
|
||||
def SetBptCndEx(ea, cnd, is_lowcnd):
|
||||
"""
|
||||
Set breakpoint condition
|
||||
|
||||
@param ea: any address in the breakpoint range
|
||||
@param cnd: breakpoint condition
|
||||
@param is_lowcnd: 0 - regular condition, 1 - low level condition
|
||||
|
||||
@return: success
|
||||
"""
|
||||
bpt = idaapi.bpt_t()
|
||||
|
||||
if not idaapi.get_bpt(ea, bpt):
|
||||
return False
|
||||
|
||||
bpt.condition = cnd
|
||||
if not is_lowcnd:
|
||||
bpt.flags |= BPT_LOWCND
|
||||
else:
|
||||
bpt.flags &= ~BPT_LOWCND
|
||||
|
||||
return idaapi.update_bpt(bpt)
|
||||
|
||||
|
||||
def SetBptCnd(ea, cnd):
|
||||
"""
|
||||
@ -7690,14 +7871,7 @@ def SetBptCnd(ea, cnd):
|
||||
|
||||
@return: success
|
||||
"""
|
||||
bpt = idaapi.bpt_t()
|
||||
|
||||
if not idaapi.get_bpt(ea, bpt):
|
||||
return False
|
||||
|
||||
bpt.condition = cnd
|
||||
|
||||
return idaapi.update_bpt(bpt)
|
||||
return SetBptCndEx(ea, cnd, 0)
|
||||
|
||||
|
||||
def AddBptEx(ea, size, bpttype):
|
||||
|
@ -68,6 +68,8 @@ def print_banner():
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
# Redirect stderr and stdout to the IDA message window
|
||||
_orig_stdout = sys.stdout;
|
||||
_orig_stderr = sys.stderr;
|
||||
sys.stdout = sys.stderr = IDAPythonStdOut()
|
||||
|
||||
# Assign a default sys.argv
|
||||
|
@ -3,7 +3,7 @@
|
||||
rem Please use the same tag for the same .i file
|
||||
rem That means if many insertions are going to happen in one given .i file then don't use more than code marking tag
|
||||
|
||||
set PY=c:\python26\python.exe
|
||||
set PY=c:\python27\python.exe
|
||||
|
||||
echo.
|
||||
echo -------- DEPLOY started --------------------------------------------------
|
||||
|
@ -168,5 +168,5 @@ plugin_t PLUGIN =
|
||||
"", // multiline help about the plugin
|
||||
|
||||
"pywraps", // the preferred short name of the plugin
|
||||
"Alt-0" // the preferred hotkey to run the plugin
|
||||
"" // the preferred hotkey to run the plugin
|
||||
};
|
||||
|
@ -571,6 +571,14 @@ def test_gpa():
|
||||
|
||||
return 1
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
def test_loaddll():
|
||||
h = loadlib("twain_32.dll")
|
||||
if h == 0:
|
||||
print "failed to load twain32 library!"
|
||||
return -1
|
||||
return 1
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# Packs a simple structure (into the database) and unpacks it back using the idaapi methods
|
||||
def test_pck_idb_raw():
|
||||
@ -884,7 +892,7 @@ def test_exec_throw():
|
||||
# all the tests that take zero parameters
|
||||
tests0 = (test_gpa, test_pck_idb_raw, test_pck_bv_raw,
|
||||
test_unpack_raw, test_pck_idb, test_pck_bv,
|
||||
test_enum_files, test2, test_exec_throw)
|
||||
test_enum_files, test2, test_exec_throw, test_loaddll)
|
||||
test_log = None # test log file
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
|
@ -152,6 +152,16 @@ static PyObject *py_get_many_bytes(ea_t ea, unsigned int size)
|
||||
//---------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
# Conversion options for get_ascii_contents2():
|
||||
ACFOPT_ASCII = 0x00000000 # convert Unicode strings to ASCII
|
||||
ACFOPT_UTF16 = 0x00000001 # return UTF-16 (aka wide-char) array for Unicode strings
|
||||
# ignored for non-Unicode strings
|
||||
ACFOPT_UTF8 = 0x00000002 # convert Unicode strings to UTF-8
|
||||
# ignored for non-Unicode strings
|
||||
ACFOPT_CONVMASK = 0x0000000F
|
||||
ACFOPT_ESCAPE = 0x00000010 # for ACFOPT_ASCII, convert non-printable
|
||||
# characters to C escapes (\n, \xNN, \uNNNN)
|
||||
|
||||
def get_ascii_contents2(ea, len, type, flags = ACFOPT_ASCII):
|
||||
"""
|
||||
Get contents of ascii string
|
||||
|
@ -562,7 +562,7 @@ private:
|
||||
|
||||
void show()
|
||||
{
|
||||
open_tform(form, FORM_MDI|FORM_TAB|FORM_MENU);
|
||||
open_tform(form, FORM_TAB|FORM_MENU);
|
||||
}
|
||||
|
||||
static py_graph_t *extract_this(PyObject *self)
|
||||
@ -666,7 +666,7 @@ private:
|
||||
qsnprintf(grnode, sizeof(grnode), "$ pygraph %s", title);
|
||||
id.create(grnode);
|
||||
gv = create_graph_viewer(form, id, s_callback, this, 0);
|
||||
open_tform(form, FORM_MDI | FORM_TAB | FORM_MENU);
|
||||
open_tform(form, FORM_TAB | FORM_MENU);
|
||||
if ( gv != NULL )
|
||||
viewer_fit_window(gv);
|
||||
}
|
||||
|
@ -619,7 +619,7 @@ def parse_command_line(cmdline):
|
||||
static PyObject *py_parse_command_line(const char *cmdline)
|
||||
{
|
||||
qstrvec_t args;
|
||||
if ( parse_command_line(cmdline, &args) == 0 )
|
||||
if ( parse_command_line2(cmdline, &args, NULL) == 0 )
|
||||
Py_RETURN_NONE;
|
||||
|
||||
PyObject *py_list = PyList_New(args.size());
|
||||
@ -729,8 +729,8 @@ static PyObject *qstrvec_t_addressof(PyObject *self, size_t idx)
|
||||
|
||||
|
||||
static bool qstrvec_t_set(
|
||||
PyObject *self,
|
||||
size_t idx,
|
||||
PyObject *self,
|
||||
size_t idx,
|
||||
const char *s)
|
||||
{
|
||||
qstrvec_t *sv = qstrvec_t_get_clink(self);
|
||||
@ -741,7 +741,7 @@ static bool qstrvec_t_set(
|
||||
}
|
||||
|
||||
static bool qstrvec_t_from_list(
|
||||
PyObject *self,
|
||||
PyObject *self,
|
||||
PyObject *py_list)
|
||||
{
|
||||
qstrvec_t *sv = qstrvec_t_get_clink(self);
|
||||
@ -781,13 +781,13 @@ static bool qstrvec_t_clear(PyObject *self, bool qclear)
|
||||
sv->qclear();
|
||||
else
|
||||
sv->clear();
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool qstrvec_t_insert(
|
||||
PyObject *self,
|
||||
size_t idx,
|
||||
PyObject *self,
|
||||
size_t idx,
|
||||
const char *s)
|
||||
{
|
||||
qstrvec_t *sv = qstrvec_t_get_clink(self);
|
||||
@ -802,7 +802,7 @@ static bool qstrvec_t_remove(PyObject *self, size_t idx)
|
||||
qstrvec_t *sv = qstrvec_t_get_clink(self);
|
||||
if ( sv == NULL || idx >= sv->size() )
|
||||
return false;
|
||||
|
||||
|
||||
sv->erase(sv->begin()+idx);
|
||||
return true;
|
||||
}
|
||||
|
@ -434,7 +434,7 @@ class IDP_Hooks(object):
|
||||
- cmd.itype must be set >= idaapi.CUSTOM_CMD_ITYPE
|
||||
- cmd.size must be set to the instruction length
|
||||
|
||||
@return: Boolean
|
||||
@return: Boolean
|
||||
- False if the instruction is not recognized
|
||||
- True if the instruction was decoded. idaapi.cmd should be filled in that case.
|
||||
"""
|
||||
|
@ -494,7 +494,7 @@ in this case.
|
||||
This flag can be used to delay the code execution
|
||||
until the next UI loop run even from the main thread"""
|
||||
|
||||
def execute_sync(callable, reqf)
|
||||
def execute_sync(callable, reqf):
|
||||
"""
|
||||
Executes a function in the context of the main thread.
|
||||
If the current thread not the main thread, then the call is queued and
|
||||
@ -567,7 +567,7 @@ static int py_execute_sync(PyObject *py_callable, int reqf)
|
||||
/*
|
||||
#<pydoc>
|
||||
|
||||
def execute_ui_requests(callable_list)
|
||||
def execute_ui_requests(callable_list):
|
||||
"""
|
||||
Inserts a list of callables into the UI message processing queue.
|
||||
When the UI is ready it will call one callable.
|
||||
@ -760,7 +760,11 @@ class UI_Hooks(object):
|
||||
IDA is terminated and the database is already closed.
|
||||
The UI may close its windows in this callback.
|
||||
"""
|
||||
pass
|
||||
# if the user forgot to call unhook, do it for him
|
||||
self.unhook()
|
||||
|
||||
def __term__(self):
|
||||
self.term()
|
||||
|
||||
#</pydoc>
|
||||
*/
|
||||
@ -769,6 +773,7 @@ class UI_Hooks
|
||||
public:
|
||||
virtual ~UI_Hooks()
|
||||
{
|
||||
unhook();
|
||||
}
|
||||
|
||||
bool hook()
|
||||
|
@ -24,10 +24,10 @@ private:
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyObject_CallMethod(
|
||||
_this->py_obj,
|
||||
(char *)S_ON_CREATE, "O",
|
||||
(char *)S_ON_CREATE, "O",
|
||||
PyCObject_FromVoidPtr(form, NULL));
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
|
||||
PyW_ShowCbErr(S_ON_CREATE);
|
||||
Py_XDECREF(py_result);
|
||||
}
|
||||
@ -40,10 +40,10 @@ private:
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyObject_CallMethod(
|
||||
_this->py_obj,
|
||||
(char *)S_ON_CLOSE, "O",
|
||||
(char *)S_ON_CLOSE, "O",
|
||||
PyCObject_FromVoidPtr(form, NULL));
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
|
||||
PyW_ShowCbErr(S_ON_CLOSE);
|
||||
Py_XDECREF(py_result);
|
||||
|
||||
@ -57,7 +57,7 @@ private:
|
||||
{
|
||||
unhook_from_notification_point(HT_UI, s_callback, this);
|
||||
form = NULL;
|
||||
|
||||
|
||||
// Call DECREF at last, since it may trigger __del__
|
||||
Py_XDECREF(py_obj);
|
||||
}
|
||||
@ -69,7 +69,7 @@ public:
|
||||
|
||||
bool show(
|
||||
PyObject *obj,
|
||||
const char *caption,
|
||||
const char *caption,
|
||||
int options)
|
||||
{
|
||||
// Already displayed?
|
||||
@ -91,7 +91,7 @@ public:
|
||||
form = create_tform(caption, NULL);
|
||||
if ( form == NULL )
|
||||
return false;
|
||||
|
||||
|
||||
if ( !hook_to_notification_point(HT_UI, s_callback, this) )
|
||||
{
|
||||
form = NULL;
|
||||
@ -119,7 +119,7 @@ public:
|
||||
{
|
||||
return PyCObject_FromVoidPtr(new plgform_t(), destroy);
|
||||
}
|
||||
|
||||
|
||||
static void destroy(void *obj)
|
||||
{
|
||||
delete (plgform_t *)obj;
|
||||
@ -137,9 +137,9 @@ static PyObject *plgform_new()
|
||||
|
||||
static bool plgform_show(
|
||||
PyObject *py_link,
|
||||
PyObject *py_obj,
|
||||
const char *caption,
|
||||
int options = FORM_MDI|FORM_TAB|FORM_MENU|FORM_RESTORE)
|
||||
PyObject *py_obj,
|
||||
const char *caption,
|
||||
int options = FORM_TAB|FORM_MENU|FORM_RESTORE)
|
||||
{
|
||||
DECL_PLGFORM;
|
||||
return plgform->show(py_obj, caption, options);
|
||||
|
@ -9,7 +9,7 @@ class PluginForm(object):
|
||||
"""
|
||||
|
||||
FORM_MDI = 0x01
|
||||
"""start by default as MDI"""
|
||||
"""start by default as MDI (obsolete)"""
|
||||
FORM_TAB = 0x02
|
||||
"""attached by default to a tab"""
|
||||
FORM_RESTORE = 0x04
|
||||
@ -38,7 +38,7 @@ class PluginForm(object):
|
||||
@param caption: The form caption
|
||||
@param options: One of PluginForm.FORM_ constants
|
||||
"""
|
||||
options |= PluginForm.FORM_MDI|PluginForm.FORM_TAB|PluginForm.FORM_MENU|PluginForm.FORM_RESTORE
|
||||
options |= PluginForm.FORM_TAB|PluginForm.FORM_MENU|PluginForm.FORM_RESTORE
|
||||
return _idaapi.plgform_show(self.__clink__, self, caption, options)
|
||||
|
||||
|
||||
|
@ -101,12 +101,12 @@ PyObject *py_unpack_object_from_idb(
|
||||
p_list *fields = (p_list *) PyString_AsString(py_fields);
|
||||
idc_value_t idc_obj;
|
||||
error_t err = unpack_object_from_idb(
|
||||
&idc_obj,
|
||||
ti,
|
||||
type,
|
||||
fields,
|
||||
ea,
|
||||
NULL,
|
||||
&idc_obj,
|
||||
ti,
|
||||
type,
|
||||
fields,
|
||||
ea,
|
||||
NULL,
|
||||
pio_flags);
|
||||
|
||||
// Unpacking failed?
|
||||
@ -116,7 +116,7 @@ PyObject *py_unpack_object_from_idb(
|
||||
// Convert
|
||||
PyObject *py_ret(NULL);
|
||||
err = idcvar_to_pyvar(idc_obj, &py_ret);
|
||||
|
||||
|
||||
// Conversion failed?
|
||||
if ( err != CIP_OK )
|
||||
return Py_BuildValue("(ii)", 0, err);
|
||||
@ -169,11 +169,11 @@ PyObject *py_unpack_object_from_bv(
|
||||
|
||||
idc_value_t idc_obj;
|
||||
error_t err = unpack_object_from_bv(
|
||||
&idc_obj,
|
||||
ti,
|
||||
type,
|
||||
fields,
|
||||
bytes,
|
||||
&idc_obj,
|
||||
ti,
|
||||
type,
|
||||
fields,
|
||||
bytes,
|
||||
pio_flags);
|
||||
|
||||
// Unpacking failed?
|
||||
|
@ -11,6 +11,7 @@
|
||||
%ignore auto_save;
|
||||
%ignore auto_term;
|
||||
%ignore ea_without_xrefs;
|
||||
%ignore postpone_lastinsn_analysis;
|
||||
|
||||
%include "auto.hpp"
|
||||
|
||||
|
10
swig/bytes.i
10
swig/bytes.i
@ -764,6 +764,16 @@ static PyObject *py_get_many_bytes(ea_t ea, unsigned int size)
|
||||
//---------------------------------------------------------------------------
|
||||
/*
|
||||
#<pydoc>
|
||||
# Conversion options for get_ascii_contents2():
|
||||
ACFOPT_ASCII = 0x00000000 # convert Unicode strings to ASCII
|
||||
ACFOPT_UTF16 = 0x00000001 # return UTF-16 (aka wide-char) array for Unicode strings
|
||||
# ignored for non-Unicode strings
|
||||
ACFOPT_UTF8 = 0x00000002 # convert Unicode strings to UTF-8
|
||||
# ignored for non-Unicode strings
|
||||
ACFOPT_CONVMASK = 0x0000000F
|
||||
ACFOPT_ESCAPE = 0x00000010 # for ACFOPT_ASCII, convert non-printable
|
||||
# characters to C escapes (\n, \xNN, \uNNNN)
|
||||
|
||||
def get_ascii_contents2(ea, len, type, flags = ACFOPT_ASCII):
|
||||
"""
|
||||
Get contents of ascii string
|
||||
|
680
swig/expr.i
680
swig/expr.i
@ -1,341 +1,341 @@
|
||||
%ignore extfun_t;
|
||||
%ignore funcset_t;
|
||||
%ignore extlang_t;
|
||||
%ignore extlang;
|
||||
%ignore extlangs_t;
|
||||
%ignore extlangs;
|
||||
%ignore register_extlang;
|
||||
%ignore IDCFuncs;
|
||||
%ignore set_idc_func;
|
||||
%ignore set_idc_dtor;
|
||||
%ignore set_idc_method;
|
||||
%ignore set_idc_getattr;
|
||||
%ignore set_idc_setattr;
|
||||
%ignore set_idc_func_ex;
|
||||
%ignore run_statements_idc;
|
||||
%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;
|
||||
%ignore calcexpr_long;
|
||||
%ignore Run;
|
||||
%ignore ExecuteLine;
|
||||
%ignore ExecuteFile;
|
||||
%ignore set_idc_func_body;
|
||||
%ignore get_idc_func_body;
|
||||
%ignore idc_stacksize;
|
||||
%ignore idc_calldepth;
|
||||
%ignore expr_printf;
|
||||
%ignore expr_sprintf;
|
||||
%ignore expr_printfer;
|
||||
%ignore init_idc;
|
||||
%ignore term_idc;
|
||||
%ignore create_default_idc_classes;
|
||||
%ignore insn_to_idc;
|
||||
%ignore find_builtin_idc_func;
|
||||
%ignore idc_mutex;
|
||||
%ignore idc_lx;
|
||||
%ignore idc_vars;
|
||||
%ignore idc_resolve_label;
|
||||
%ignore idc_resolver_ea;
|
||||
%ignore setup_lowcnd_regfuncs;
|
||||
%cstring_output_maxstr_none(char *errbuf, size_t errbufsize);
|
||||
|
||||
%ignore CompileEx;
|
||||
%rename (CompileEx) CompileEx_wrap;
|
||||
%ignore Compile;
|
||||
%rename (Compile) Compile_wrap;
|
||||
%ignore calcexpr;
|
||||
%rename (calcexpr) calcexpr_wrap;
|
||||
%ignore calc_idc_expr;
|
||||
%rename (calc_idc_expr) calc_idc_expr_wrap;
|
||||
%ignore CompileLine(const char *line, char *errbuf, size_t errbufsize, uval_t (idaapi*_getname)(const char *name)=NULL);
|
||||
%ignore CompileLineEx;
|
||||
%ignore CompileLine;
|
||||
%rename (CompileLine) CompileLine_wrap;
|
||||
%{
|
||||
//<code(py_expr)>
|
||||
struct py_idcfunc_ctx_t
|
||||
{
|
||||
PyObject *py_func;
|
||||
qstring name;
|
||||
int nargs;
|
||||
py_idcfunc_ctx_t(PyObject *py_func, const char *name, int nargs): py_func(py_func), name(name), nargs(nargs)
|
||||
{
|
||||
Py_INCREF(py_func);
|
||||
}
|
||||
~py_idcfunc_ctx_t()
|
||||
{
|
||||
Py_DECREF(py_func);
|
||||
}
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
static error_t py_call_idc_func(
|
||||
void *_ctx,
|
||||
idc_value_t *argv,
|
||||
idc_value_t *r)
|
||||
{
|
||||
// Convert IDC arguments to Python list
|
||||
py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)_ctx;
|
||||
int cvt;
|
||||
ppyobject_vec_t pargs;
|
||||
char errbuf[MAXSTR];
|
||||
if ( !pyw_convert_idc_args(argv, ctx->nargs, pargs, NULL, errbuf, sizeof(errbuf)) )
|
||||
{
|
||||
// Error during conversion? Create an IDC exception
|
||||
return PyW_CreateIdcException(r, errbuf);
|
||||
}
|
||||
|
||||
// Call the Python function
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyObject_CallObject(
|
||||
ctx->py_func,
|
||||
pargs.empty() ? NULL : pargs[0]);
|
||||
|
||||
error_t err;
|
||||
if ( PyW_GetError(errbuf, sizeof(errbuf)) )
|
||||
{
|
||||
err = PyW_CreateIdcException(r, errbuf);
|
||||
Py_XDECREF(py_result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert the result to IDC
|
||||
r->clear();
|
||||
cvt = pyvar_to_idcvar(py_result, r);
|
||||
if ( cvt < CIP_OK )
|
||||
err = PyW_CreateIdcException(r, "ERROR: bad return value");
|
||||
else
|
||||
err = eOk;
|
||||
if ( cvt != CIP_OK_NODECREF )
|
||||
Py_XDECREF(py_result);
|
||||
}
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
// Free the converted args
|
||||
pyw_free_idc_args(pargs);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
//</code(py_expr)>
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
//<inline(py_expr)>
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
static size_t py_get_call_idc_func()
|
||||
{
|
||||
return (size_t)py_call_idc_func;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Internal function:
|
||||
// - capture the python callable
|
||||
// - return a C context as a numeric value
|
||||
static size_t pyw_register_idc_func(
|
||||
const char *name,
|
||||
const char *args,
|
||||
PyObject *py_fp)
|
||||
{
|
||||
return (size_t)new py_idcfunc_ctx_t(py_fp, name, strlen(args));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Internal function:
|
||||
// - free the C context
|
||||
static bool pyw_unregister_idc_func(size_t ctxptr)
|
||||
{
|
||||
// Unregister the function
|
||||
py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)ctxptr;
|
||||
bool ok = set_idc_func_ex(ctx->name.c_str(), NULL, NULL, 0);
|
||||
|
||||
// Delete the context
|
||||
delete ctx;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
static bool py_set_idc_func_ex(
|
||||
const char *name,
|
||||
size_t fp_ptr,
|
||||
const char *args,
|
||||
int flags)
|
||||
{
|
||||
return set_idc_func_ex(name, (idc_func_t *)fp_ptr, args, flags);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Compile* functions return false when error so the return
|
||||
// value must be negated for the error string to be returned
|
||||
bool CompileEx_wrap(
|
||||
const char *file,
|
||||
bool del_macros,
|
||||
char *errbuf, size_t errbufsize)
|
||||
{
|
||||
return !CompileEx(file, del_macros, errbuf, errbufsize);
|
||||
}
|
||||
|
||||
bool Compile_wrap(const char *file, char *errbuf, size_t errbufsize)
|
||||
{
|
||||
return !Compile(file, errbuf, errbufsize);
|
||||
}
|
||||
|
||||
bool calcexpr_wrap(
|
||||
ea_t where,
|
||||
const char *line,
|
||||
idc_value_t *rv,
|
||||
char *errbuf, size_t errbufsize)
|
||||
{
|
||||
return !calcexpr(where, line, rv, errbuf, errbufsize);
|
||||
}
|
||||
|
||||
bool calc_idc_expr_wrap(
|
||||
ea_t where,
|
||||
const char *line,
|
||||
idc_value_t *rv,
|
||||
char *errbuf, size_t errbufsize)
|
||||
{
|
||||
return !calc_idc_expr(where, line, rv, errbuf, errbufsize);
|
||||
}
|
||||
|
||||
bool CompileLine_wrap(const char *line, char *errbuf, size_t errbufsize)
|
||||
{
|
||||
return !CompileLineEx(line, errbuf, errbufsize);
|
||||
}
|
||||
|
||||
//</inline(py_expr)>
|
||||
%}
|
||||
|
||||
%include "expr.hpp"
|
||||
|
||||
%pythoncode %{
|
||||
|
||||
#<pycode(py_expr)>
|
||||
try:
|
||||
import types
|
||||
import ctypes
|
||||
# Callback for IDC func callback (On Windows, we use stdcall)
|
||||
# typedef error_t idaapi idc_func_t(idc_value_t *argv,idc_value_t *r);
|
||||
_IDCFUNC_CB_T = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p)
|
||||
|
||||
# A trampoline function that is called from idcfunc_t that will
|
||||
# call the Python callback with the argv and r properly serialized to python
|
||||
call_idc_func__ = ctypes.CFUNCTYPE(ctypes.c_long)(_idaapi.py_get_call_idc_func())
|
||||
except:
|
||||
def call_idc_func__(*args):
|
||||
warning("IDC extensions need ctypes library in order to work")
|
||||
return 0
|
||||
try:
|
||||
_IDCFUNC_CB_T = CFUNCTYPE(c_int, c_void_p, c_void_p)
|
||||
except:
|
||||
_IDCFUNC_CB_T = None
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
EXTFUN_BASE = 0x0001
|
||||
"""requires open database"""
|
||||
EXTFUN_NORET = 0x0002
|
||||
"""does not return. the interpreter may clean up its state before calling it."""
|
||||
EXTFUN_SAFE = 0x0004
|
||||
"""thread safe function. may be called"""
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
class _IdcFunction(object):
|
||||
"""
|
||||
Internal class that calls pyw_call_idc_func() with a context
|
||||
"""
|
||||
def __init__(self, ctxptr):
|
||||
self.ctxptr = ctxptr
|
||||
# Take a reference to the ctypes callback
|
||||
# (note: this will create a circular reference)
|
||||
self.cb = _IDCFUNC_CB_T(self)
|
||||
|
||||
fp_ptr = property(lambda self: ctypes.cast(self.cb, ctypes.c_void_p).value)
|
||||
|
||||
def __call__(self, args, res):
|
||||
return call_idc_func__(self.ctxptr, args, res)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Dictionary to remember IDC function names along with the context pointer
|
||||
# retrieved by using the internal pyw_register_idc_func()
|
||||
__IDC_FUNC_CTXS = {}
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def set_idc_func_ex(name, fp=None, args=(), flags=0):
|
||||
"""
|
||||
Extends the IDC language by exposing a new IDC function that is backed up by a Python function
|
||||
This function also unregisters the IDC function if 'fp' was passed as None
|
||||
|
||||
@param name: IDC function name to expose
|
||||
@param fp: Python callable that will receive the arguments and return a tuple.
|
||||
If this argument is None then the IDC function is unregistered
|
||||
@param args: Arguments. A tuple of idaapi.VT_XXX constants
|
||||
@param flags: IDC function flags. A combination of EXTFUN_XXX constants
|
||||
|
||||
@return: Boolean.
|
||||
"""
|
||||
global __IDC_FUNC_CTXS
|
||||
|
||||
# Get the context
|
||||
f = __IDC_FUNC_CTXS.get(name, None)
|
||||
|
||||
# Unregistering?
|
||||
if fp is None:
|
||||
# Not registered?
|
||||
if f is None:
|
||||
return False
|
||||
|
||||
# Break circular reference
|
||||
del f.cb
|
||||
|
||||
# Delete the name from the dictionary
|
||||
del __IDC_FUNC_CTXS[name]
|
||||
|
||||
# Delete the context and unregister the function
|
||||
return _idaapi.pyw_unregister_idc_func(f.ctxptr)
|
||||
|
||||
# Registering a function that is already registered?
|
||||
if f is not None:
|
||||
# Unregister it first
|
||||
set_idc_func_ex(name, None)
|
||||
|
||||
# Convert the tupple argument info to a string
|
||||
args = "".join([chr(x) for x in args])
|
||||
|
||||
# Create a context
|
||||
ctxptr = _idaapi.pyw_register_idc_func(name, args, fp)
|
||||
if ctxptr == 0:
|
||||
return False
|
||||
|
||||
# Bind the context with the IdcFunc object
|
||||
f = _IdcFunction(ctxptr)
|
||||
|
||||
# Remember the Python context
|
||||
__IDC_FUNC_CTXS[name] = f
|
||||
|
||||
# Register IDC function with a callback
|
||||
return _idaapi.py_set_idc_func_ex(
|
||||
name,
|
||||
f.fp_ptr,
|
||||
args,
|
||||
flags)
|
||||
|
||||
#</pycode(py_expr)>
|
||||
%ignore extfun_t;
|
||||
%ignore funcset_t;
|
||||
%ignore extlang_t;
|
||||
%ignore extlang;
|
||||
%ignore extlangs_t;
|
||||
%ignore extlangs;
|
||||
%ignore register_extlang;
|
||||
%ignore IDCFuncs;
|
||||
%ignore set_idc_func;
|
||||
%ignore set_idc_dtor;
|
||||
%ignore set_idc_method;
|
||||
%ignore set_idc_getattr;
|
||||
%ignore set_idc_setattr;
|
||||
%ignore set_idc_func_ex;
|
||||
%ignore run_statements_idc;
|
||||
%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;
|
||||
%ignore calcexpr_long;
|
||||
%ignore Run;
|
||||
%ignore ExecuteLine;
|
||||
%ignore ExecuteFile;
|
||||
%ignore set_idc_func_body;
|
||||
%ignore get_idc_func_body;
|
||||
%ignore idc_stacksize;
|
||||
%ignore idc_calldepth;
|
||||
%ignore expr_printf;
|
||||
%ignore expr_sprintf;
|
||||
%ignore expr_printfer;
|
||||
%ignore init_idc;
|
||||
%ignore term_idc;
|
||||
%ignore create_default_idc_classes;
|
||||
%ignore insn_to_idc;
|
||||
%ignore find_builtin_idc_func;
|
||||
%ignore idc_mutex;
|
||||
%ignore idc_lx;
|
||||
%ignore idc_vars;
|
||||
%ignore idc_resolve_label;
|
||||
%ignore idc_resolver_ea;
|
||||
%ignore setup_lowcnd_regfuncs;
|
||||
%cstring_output_maxstr_none(char *errbuf, size_t errbufsize);
|
||||
|
||||
%ignore CompileEx;
|
||||
%rename (CompileEx) CompileEx_wrap;
|
||||
%ignore Compile;
|
||||
%rename (Compile) Compile_wrap;
|
||||
%ignore calcexpr;
|
||||
%rename (calcexpr) calcexpr_wrap;
|
||||
%ignore calc_idc_expr;
|
||||
%rename (calc_idc_expr) calc_idc_expr_wrap;
|
||||
%ignore CompileLine(const char *line, char *errbuf, size_t errbufsize, uval_t (idaapi*_getname)(const char *name)=NULL);
|
||||
%ignore CompileLineEx;
|
||||
%ignore CompileLine;
|
||||
%rename (CompileLine) CompileLine_wrap;
|
||||
%{
|
||||
//<code(py_expr)>
|
||||
struct py_idcfunc_ctx_t
|
||||
{
|
||||
PyObject *py_func;
|
||||
qstring name;
|
||||
int nargs;
|
||||
py_idcfunc_ctx_t(PyObject *py_func, const char *name, int nargs): py_func(py_func), name(name), nargs(nargs)
|
||||
{
|
||||
Py_INCREF(py_func);
|
||||
}
|
||||
~py_idcfunc_ctx_t()
|
||||
{
|
||||
Py_DECREF(py_func);
|
||||
}
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
static error_t py_call_idc_func(
|
||||
void *_ctx,
|
||||
idc_value_t *argv,
|
||||
idc_value_t *r)
|
||||
{
|
||||
// Convert IDC arguments to Python list
|
||||
py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)_ctx;
|
||||
int cvt;
|
||||
ppyobject_vec_t pargs;
|
||||
char errbuf[MAXSTR];
|
||||
if ( !pyw_convert_idc_args(argv, ctx->nargs, pargs, NULL, errbuf, sizeof(errbuf)) )
|
||||
{
|
||||
// Error during conversion? Create an IDC exception
|
||||
return PyW_CreateIdcException(r, errbuf);
|
||||
}
|
||||
|
||||
// Call the Python function
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyObject_CallObject(
|
||||
ctx->py_func,
|
||||
pargs.empty() ? NULL : pargs[0]);
|
||||
|
||||
error_t err;
|
||||
if ( PyW_GetError(errbuf, sizeof(errbuf)) )
|
||||
{
|
||||
err = PyW_CreateIdcException(r, errbuf);
|
||||
Py_XDECREF(py_result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert the result to IDC
|
||||
r->clear();
|
||||
cvt = pyvar_to_idcvar(py_result, r);
|
||||
if ( cvt < CIP_OK )
|
||||
err = PyW_CreateIdcException(r, "ERROR: bad return value");
|
||||
else
|
||||
err = eOk;
|
||||
if ( cvt != CIP_OK_NODECREF )
|
||||
Py_XDECREF(py_result);
|
||||
}
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
// Free the converted args
|
||||
pyw_free_idc_args(pargs);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
//</code(py_expr)>
|
||||
%}
|
||||
|
||||
%inline %{
|
||||
//<inline(py_expr)>
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
static size_t py_get_call_idc_func()
|
||||
{
|
||||
return (size_t)py_call_idc_func;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Internal function:
|
||||
// - capture the python callable
|
||||
// - return a C context as a numeric value
|
||||
static size_t pyw_register_idc_func(
|
||||
const char *name,
|
||||
const char *args,
|
||||
PyObject *py_fp)
|
||||
{
|
||||
return (size_t)new py_idcfunc_ctx_t(py_fp, name, strlen(args));
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Internal function:
|
||||
// - free the C context
|
||||
static bool pyw_unregister_idc_func(size_t ctxptr)
|
||||
{
|
||||
// Unregister the function
|
||||
py_idcfunc_ctx_t *ctx = (py_idcfunc_ctx_t *)ctxptr;
|
||||
bool ok = set_idc_func_ex(ctx->name.c_str(), NULL, NULL, 0);
|
||||
|
||||
// Delete the context
|
||||
delete ctx;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
static bool py_set_idc_func_ex(
|
||||
const char *name,
|
||||
size_t fp_ptr,
|
||||
const char *args,
|
||||
int flags)
|
||||
{
|
||||
return set_idc_func_ex(name, (idc_func_t *)fp_ptr, args, flags);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Compile* functions return false when error so the return
|
||||
// value must be negated for the error string to be returned
|
||||
bool CompileEx_wrap(
|
||||
const char *file,
|
||||
bool del_macros,
|
||||
char *errbuf, size_t errbufsize)
|
||||
{
|
||||
return !CompileEx(file, del_macros, errbuf, errbufsize);
|
||||
}
|
||||
|
||||
bool Compile_wrap(const char *file, char *errbuf, size_t errbufsize)
|
||||
{
|
||||
return !Compile(file, errbuf, errbufsize);
|
||||
}
|
||||
|
||||
bool calcexpr_wrap(
|
||||
ea_t where,
|
||||
const char *line,
|
||||
idc_value_t *rv,
|
||||
char *errbuf, size_t errbufsize)
|
||||
{
|
||||
return !calcexpr(where, line, rv, errbuf, errbufsize);
|
||||
}
|
||||
|
||||
bool calc_idc_expr_wrap(
|
||||
ea_t where,
|
||||
const char *line,
|
||||
idc_value_t *rv,
|
||||
char *errbuf, size_t errbufsize)
|
||||
{
|
||||
return !calc_idc_expr(where, line, rv, errbuf, errbufsize);
|
||||
}
|
||||
|
||||
bool CompileLine_wrap(const char *line, char *errbuf, size_t errbufsize)
|
||||
{
|
||||
return !CompileLineEx(line, errbuf, errbufsize);
|
||||
}
|
||||
|
||||
//</inline(py_expr)>
|
||||
%}
|
||||
|
||||
%include "expr.hpp"
|
||||
|
||||
%pythoncode %{
|
||||
|
||||
#<pycode(py_expr)>
|
||||
try:
|
||||
import types
|
||||
import ctypes
|
||||
# Callback for IDC func callback (On Windows, we use stdcall)
|
||||
# typedef error_t idaapi idc_func_t(idc_value_t *argv,idc_value_t *r);
|
||||
_IDCFUNC_CB_T = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p)
|
||||
|
||||
# A trampoline function that is called from idcfunc_t that will
|
||||
# call the Python callback with the argv and r properly serialized to python
|
||||
call_idc_func__ = ctypes.CFUNCTYPE(ctypes.c_long)(_idaapi.py_get_call_idc_func())
|
||||
except:
|
||||
def call_idc_func__(*args):
|
||||
warning("IDC extensions need ctypes library in order to work")
|
||||
return 0
|
||||
try:
|
||||
_IDCFUNC_CB_T = CFUNCTYPE(c_int, c_void_p, c_void_p)
|
||||
except:
|
||||
_IDCFUNC_CB_T = None
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
EXTFUN_BASE = 0x0001
|
||||
"""requires open database"""
|
||||
EXTFUN_NORET = 0x0002
|
||||
"""does not return. the interpreter may clean up its state before calling it."""
|
||||
EXTFUN_SAFE = 0x0004
|
||||
"""thread safe function. may be called"""
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
class _IdcFunction(object):
|
||||
"""
|
||||
Internal class that calls pyw_call_idc_func() with a context
|
||||
"""
|
||||
def __init__(self, ctxptr):
|
||||
self.ctxptr = ctxptr
|
||||
# Take a reference to the ctypes callback
|
||||
# (note: this will create a circular reference)
|
||||
self.cb = _IDCFUNC_CB_T(self)
|
||||
|
||||
fp_ptr = property(lambda self: ctypes.cast(self.cb, ctypes.c_void_p).value)
|
||||
|
||||
def __call__(self, args, res):
|
||||
return call_idc_func__(self.ctxptr, args, res)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# Dictionary to remember IDC function names along with the context pointer
|
||||
# retrieved by using the internal pyw_register_idc_func()
|
||||
__IDC_FUNC_CTXS = {}
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
def set_idc_func_ex(name, fp=None, args=(), flags=0):
|
||||
"""
|
||||
Extends the IDC language by exposing a new IDC function that is backed up by a Python function
|
||||
This function also unregisters the IDC function if 'fp' was passed as None
|
||||
|
||||
@param name: IDC function name to expose
|
||||
@param fp: Python callable that will receive the arguments and return a tuple.
|
||||
If this argument is None then the IDC function is unregistered
|
||||
@param args: Arguments. A tuple of idaapi.VT_XXX constants
|
||||
@param flags: IDC function flags. A combination of EXTFUN_XXX constants
|
||||
|
||||
@return: Boolean.
|
||||
"""
|
||||
global __IDC_FUNC_CTXS
|
||||
|
||||
# Get the context
|
||||
f = __IDC_FUNC_CTXS.get(name, None)
|
||||
|
||||
# Unregistering?
|
||||
if fp is None:
|
||||
# Not registered?
|
||||
if f is None:
|
||||
return False
|
||||
|
||||
# Break circular reference
|
||||
del f.cb
|
||||
|
||||
# Delete the name from the dictionary
|
||||
del __IDC_FUNC_CTXS[name]
|
||||
|
||||
# Delete the context and unregister the function
|
||||
return _idaapi.pyw_unregister_idc_func(f.ctxptr)
|
||||
|
||||
# Registering a function that is already registered?
|
||||
if f is not None:
|
||||
# Unregister it first
|
||||
set_idc_func_ex(name, None)
|
||||
|
||||
# Convert the tupple argument info to a string
|
||||
args = "".join([chr(x) for x in args])
|
||||
|
||||
# Create a context
|
||||
ctxptr = _idaapi.pyw_register_idc_func(name, args, fp)
|
||||
if ctxptr == 0:
|
||||
return False
|
||||
|
||||
# Bind the context with the IdcFunc object
|
||||
f = _IdcFunction(ctxptr)
|
||||
|
||||
# Remember the Python context
|
||||
__IDC_FUNC_CTXS[name] = f
|
||||
|
||||
# Register IDC function with a callback
|
||||
return _idaapi.py_set_idc_func_ex(
|
||||
name,
|
||||
f.fp_ptr,
|
||||
args,
|
||||
flags)
|
||||
|
||||
#</pycode(py_expr)>
|
||||
%}
|
@ -62,9 +62,8 @@ static ea_t get_fchunk_referer(ea_t ea, size_t idx)
|
||||
def get_idasgn_desc(n):
|
||||
"""
|
||||
Get information about a signature in the list.
|
||||
It returns both:
|
||||
signame - the name of the signature
|
||||
optlibs - the names of the optional libraries
|
||||
It returns both: the name of the signature, and names of the
|
||||
optional libraries
|
||||
|
||||
@param n: number of signature in the list (0..get_idasgn_qty()-1)
|
||||
@return: None on failure or tuple(signame, optlibs)
|
||||
|
@ -564,7 +564,7 @@ private:
|
||||
|
||||
void show()
|
||||
{
|
||||
open_tform(form, FORM_MDI|FORM_TAB|FORM_MENU);
|
||||
open_tform(form, FORM_TAB|FORM_MENU);
|
||||
}
|
||||
|
||||
static py_graph_t *extract_this(PyObject *self)
|
||||
@ -668,7 +668,7 @@ private:
|
||||
qsnprintf(grnode, sizeof(grnode), "$ pygraph %s", title);
|
||||
id.create(grnode);
|
||||
gv = create_graph_viewer(form, id, s_callback, this, 0);
|
||||
open_tform(form, FORM_MDI | FORM_TAB | FORM_MENU);
|
||||
open_tform(form, FORM_TAB | FORM_MENU);
|
||||
if ( gv != NULL )
|
||||
viewer_fit_window(gv);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
%constant size_t SIZE_MAX = size_t(-1);
|
||||
|
||||
// Enable automatic docstring generation
|
||||
%feature(autodoc);
|
||||
%feature(autodoc,0);
|
||||
|
||||
%define SWIG_DECLARE_PY_CLINKED_OBJECT(type)
|
||||
%inline %{
|
||||
@ -2056,11 +2056,11 @@ bool pywraps_nw_term()
|
||||
{
|
||||
if ( g_nw == NULL )
|
||||
return true;
|
||||
|
||||
|
||||
// If could not deinitialize then return w/o stopping nw
|
||||
if ( !g_nw->deinit() )
|
||||
return false;
|
||||
|
||||
|
||||
// Cleanup
|
||||
delete g_nw;
|
||||
g_nw = NULL;
|
||||
@ -2694,7 +2694,7 @@ def parse_command_line(cmdline):
|
||||
static PyObject *py_parse_command_line(const char *cmdline)
|
||||
{
|
||||
qstrvec_t args;
|
||||
if ( parse_command_line(cmdline, &args) == 0 )
|
||||
if ( parse_command_line2(cmdline, &args, NULL) == 0 )
|
||||
Py_RETURN_NONE;
|
||||
|
||||
PyObject *py_list = PyList_New(args.size());
|
||||
|
@ -475,7 +475,7 @@ class IDP_Hooks(object):
|
||||
- cmd.itype must be set >= idaapi.CUSTOM_CMD_ITYPE
|
||||
- cmd.size must be set to the instruction length
|
||||
|
||||
@return: Boolean
|
||||
@return: Boolean
|
||||
- False if the instruction is not recognized
|
||||
- True if the instruction was decoded. idaapi.cmd should be filled in that case.
|
||||
"""
|
||||
|
@ -619,7 +619,7 @@ in this case.
|
||||
This flag can be used to delay the code execution
|
||||
until the next UI loop run even from the main thread"""
|
||||
|
||||
def execute_sync(callable, reqf)
|
||||
def execute_sync(callable, reqf):
|
||||
"""
|
||||
Executes a function in the context of the main thread.
|
||||
If the current thread not the main thread, then the call is queued and
|
||||
@ -692,7 +692,7 @@ static int py_execute_sync(PyObject *py_callable, int reqf)
|
||||
/*
|
||||
#<pydoc>
|
||||
|
||||
def execute_ui_requests(callable_list)
|
||||
def execute_ui_requests(callable_list):
|
||||
"""
|
||||
Inserts a list of callables into the UI message processing queue.
|
||||
When the UI is ready it will call one callable.
|
||||
@ -885,7 +885,11 @@ class UI_Hooks(object):
|
||||
IDA is terminated and the database is already closed.
|
||||
The UI may close its windows in this callback.
|
||||
"""
|
||||
pass
|
||||
# if the user forgot to call unhook, do it for him
|
||||
self.unhook()
|
||||
|
||||
def __term__(self):
|
||||
self.term()
|
||||
|
||||
#</pydoc>
|
||||
*/
|
||||
@ -894,6 +898,7 @@ class UI_Hooks
|
||||
public:
|
||||
virtual ~UI_Hooks()
|
||||
{
|
||||
unhook();
|
||||
}
|
||||
|
||||
bool hook()
|
||||
@ -2690,10 +2695,10 @@ private:
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyObject_CallMethod(
|
||||
_this->py_obj,
|
||||
(char *)S_ON_CREATE, "O",
|
||||
(char *)S_ON_CREATE, "O",
|
||||
PyCObject_FromVoidPtr(form, NULL));
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
|
||||
PyW_ShowCbErr(S_ON_CREATE);
|
||||
Py_XDECREF(py_result);
|
||||
}
|
||||
@ -2706,10 +2711,10 @@ private:
|
||||
PYW_GIL_ENSURE;
|
||||
PyObject *py_result = PyObject_CallMethod(
|
||||
_this->py_obj,
|
||||
(char *)S_ON_CLOSE, "O",
|
||||
(char *)S_ON_CLOSE, "O",
|
||||
PyCObject_FromVoidPtr(form, NULL));
|
||||
PYW_GIL_RELEASE;
|
||||
|
||||
|
||||
PyW_ShowCbErr(S_ON_CLOSE);
|
||||
Py_XDECREF(py_result);
|
||||
|
||||
@ -2723,7 +2728,7 @@ private:
|
||||
{
|
||||
unhook_from_notification_point(HT_UI, s_callback, this);
|
||||
form = NULL;
|
||||
|
||||
|
||||
// Call DECREF at last, since it may trigger __del__
|
||||
Py_XDECREF(py_obj);
|
||||
}
|
||||
@ -2735,7 +2740,7 @@ public:
|
||||
|
||||
bool show(
|
||||
PyObject *obj,
|
||||
const char *caption,
|
||||
const char *caption,
|
||||
int options)
|
||||
{
|
||||
// Already displayed?
|
||||
@ -2757,7 +2762,7 @@ public:
|
||||
form = create_tform(caption, NULL);
|
||||
if ( form == NULL )
|
||||
return false;
|
||||
|
||||
|
||||
if ( !hook_to_notification_point(HT_UI, s_callback, this) )
|
||||
{
|
||||
form = NULL;
|
||||
@ -2785,7 +2790,7 @@ public:
|
||||
{
|
||||
return PyCObject_FromVoidPtr(new plgform_t(), destroy);
|
||||
}
|
||||
|
||||
|
||||
static void destroy(void *obj)
|
||||
{
|
||||
delete (plgform_t *)obj;
|
||||
@ -2805,9 +2810,9 @@ static PyObject *plgform_new()
|
||||
|
||||
static bool plgform_show(
|
||||
PyObject *py_link,
|
||||
PyObject *py_obj,
|
||||
const char *caption,
|
||||
int options = FORM_MDI|FORM_TAB|FORM_MENU|FORM_RESTORE)
|
||||
PyObject *py_obj,
|
||||
const char *caption,
|
||||
int options = FORM_TAB|FORM_MENU|FORM_RESTORE)
|
||||
{
|
||||
DECL_PLGFORM;
|
||||
return plgform->show(py_obj, caption, options);
|
||||
@ -5531,7 +5536,7 @@ class PluginForm(object):
|
||||
"""
|
||||
|
||||
FORM_MDI = 0x01
|
||||
"""start by default as MDI"""
|
||||
"""start by default as MDI (obsolete)"""
|
||||
FORM_TAB = 0x02
|
||||
"""attached by default to a tab"""
|
||||
FORM_RESTORE = 0x04
|
||||
@ -5560,7 +5565,7 @@ class PluginForm(object):
|
||||
@param caption: The form caption
|
||||
@param options: One of PluginForm.FORM_ constants
|
||||
"""
|
||||
options |= PluginForm.FORM_MDI|PluginForm.FORM_TAB|PluginForm.FORM_MENU|PluginForm.FORM_RESTORE
|
||||
options |= PluginForm.FORM_TAB|PluginForm.FORM_MENU|PluginForm.FORM_RESTORE
|
||||
return _idaapi.plgform_show(self.__clink__, self, caption, options)
|
||||
|
||||
|
||||
|
222
swig/name.i
222
swig/name.i
@ -1,111 +1,111 @@
|
||||
%cstring_output_maxstr_none(char *buf, int bufsize);
|
||||
|
||||
%cstring_bounded_output(char *dstname, MAXSTR);
|
||||
%cstring_bounded_output(char *buf, MAXSTR);
|
||||
|
||||
// This is for get_name_value's output value
|
||||
%apply unsigned long *OUTPUT { uval_t *value };
|
||||
|
||||
// FIXME: These should be fixed
|
||||
%ignore append_struct_fields;
|
||||
%ignore get_struct_operand;
|
||||
%ignore set_debug_names;
|
||||
%ignore get_debug_name;
|
||||
%ignore nameVa;
|
||||
|
||||
// Unexported & kernel-only
|
||||
%ignore get_short_name;
|
||||
%ignore get_long_name;
|
||||
%ignore get_colored_short_name;
|
||||
%ignore get_colored_long_name;
|
||||
%ignore addDummyName;
|
||||
%ignore convert_debug_names_to_normal;
|
||||
%ignore convert_name_formats;
|
||||
%ignore showhide_name;
|
||||
%ignore clear_lname_bit;
|
||||
%ignore fix_new_name;
|
||||
%ignore rename;
|
||||
%ignore move_names;
|
||||
%ignore is_noret_name;
|
||||
%ignore is_exit_name;
|
||||
%ignore dummy_name_ea;
|
||||
|
||||
%ignore get_debug_names;
|
||||
%rename (get_debug_names) py_get_debug_names;
|
||||
%inline %{
|
||||
//<inline(py_name)>
|
||||
//------------------------------------------------------------------------
|
||||
PyObject *py_get_debug_names(ea_t ea1, ea_t ea2)
|
||||
{
|
||||
// Get debug names
|
||||
ea_name_vec_t names;
|
||||
get_debug_names(ea1, ea2, names);
|
||||
PyObject *dict = Py_BuildValue("{}");
|
||||
if (dict == NULL)
|
||||
return NULL;
|
||||
|
||||
for (ea_name_vec_t::iterator it=names.begin();it!=names.end();++it)
|
||||
{
|
||||
PyDict_SetItem(dict,
|
||||
Py_BuildValue(PY_FMT64, it->ea),
|
||||
PyString_FromString(it->name.c_str()));
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
//</inline(py_name)>
|
||||
%}
|
||||
|
||||
%pythoncode %{
|
||||
#<pycode(py_name)>
|
||||
|
||||
class NearestName:
|
||||
"""
|
||||
Utility class to help find the nearest name in a given ea/name dictionary
|
||||
"""
|
||||
def __init__(self, ea_names):
|
||||
self.update(ea_names)
|
||||
|
||||
|
||||
def update(self, ea_names):
|
||||
"""Updates the ea/names map"""
|
||||
self._names = ea_names
|
||||
self._addrs = ea_names.keys()
|
||||
self._addrs.sort()
|
||||
|
||||
|
||||
def find(self, ea):
|
||||
"""
|
||||
Returns a tupple (ea, name, pos) that is the nearest to the passed ea
|
||||
If no name is matched then None is returned
|
||||
"""
|
||||
pos = bisect.bisect_left(self._addrs, ea)
|
||||
# no match
|
||||
if pos >= len(self._addrs):
|
||||
return None
|
||||
# exact match?
|
||||
if self._addrs[pos] != ea:
|
||||
pos -= 1 # go to previous element
|
||||
if pos < 0:
|
||||
return None
|
||||
return self[pos]
|
||||
|
||||
|
||||
def _get_item(self, index):
|
||||
ea = self._addrs[index]
|
||||
return (ea, self._names[ea], index)
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
return (self._get_item(index) for index in xrange(0, len(self._addrs)))
|
||||
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Returns the tupple (ea, name, index)"""
|
||||
if index > len(self._addrs):
|
||||
raise StopIteration
|
||||
return self._get_item(index)
|
||||
|
||||
#</pycode(py_name)>
|
||||
%}
|
||||
%include "name.hpp"
|
||||
%cstring_output_maxstr_none(char *buf, int bufsize);
|
||||
|
||||
%cstring_bounded_output(char *dstname, MAXSTR);
|
||||
%cstring_bounded_output(char *buf, MAXSTR);
|
||||
|
||||
// This is for get_name_value's output value
|
||||
%apply unsigned long *OUTPUT { uval_t *value };
|
||||
|
||||
// FIXME: These should be fixed
|
||||
%ignore append_struct_fields;
|
||||
%ignore get_struct_operand;
|
||||
%ignore set_debug_names;
|
||||
%ignore get_debug_name;
|
||||
%ignore nameVa;
|
||||
|
||||
// Unexported & kernel-only
|
||||
%ignore get_short_name;
|
||||
%ignore get_long_name;
|
||||
%ignore get_colored_short_name;
|
||||
%ignore get_colored_long_name;
|
||||
%ignore addDummyName;
|
||||
%ignore convert_debug_names_to_normal;
|
||||
%ignore convert_name_formats;
|
||||
%ignore showhide_name;
|
||||
%ignore clear_lname_bit;
|
||||
%ignore fix_new_name;
|
||||
%ignore rename;
|
||||
%ignore move_names;
|
||||
%ignore is_noret_name;
|
||||
%ignore is_exit_name;
|
||||
%ignore dummy_name_ea;
|
||||
|
||||
%ignore get_debug_names;
|
||||
%rename (get_debug_names) py_get_debug_names;
|
||||
%inline %{
|
||||
//<inline(py_name)>
|
||||
//------------------------------------------------------------------------
|
||||
PyObject *py_get_debug_names(ea_t ea1, ea_t ea2)
|
||||
{
|
||||
// Get debug names
|
||||
ea_name_vec_t names;
|
||||
get_debug_names(ea1, ea2, names);
|
||||
PyObject *dict = Py_BuildValue("{}");
|
||||
if (dict == NULL)
|
||||
return NULL;
|
||||
|
||||
for (ea_name_vec_t::iterator it=names.begin();it!=names.end();++it)
|
||||
{
|
||||
PyDict_SetItem(dict,
|
||||
Py_BuildValue(PY_FMT64, it->ea),
|
||||
PyString_FromString(it->name.c_str()));
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
//------------------------------------------------------------------------
|
||||
//</inline(py_name)>
|
||||
%}
|
||||
|
||||
%pythoncode %{
|
||||
#<pycode(py_name)>
|
||||
|
||||
class NearestName:
|
||||
"""
|
||||
Utility class to help find the nearest name in a given ea/name dictionary
|
||||
"""
|
||||
def __init__(self, ea_names):
|
||||
self.update(ea_names)
|
||||
|
||||
|
||||
def update(self, ea_names):
|
||||
"""Updates the ea/names map"""
|
||||
self._names = ea_names
|
||||
self._addrs = ea_names.keys()
|
||||
self._addrs.sort()
|
||||
|
||||
|
||||
def find(self, ea):
|
||||
"""
|
||||
Returns a tupple (ea, name, pos) that is the nearest to the passed ea
|
||||
If no name is matched then None is returned
|
||||
"""
|
||||
pos = bisect.bisect_left(self._addrs, ea)
|
||||
# no match
|
||||
if pos >= len(self._addrs):
|
||||
return None
|
||||
# exact match?
|
||||
if self._addrs[pos] != ea:
|
||||
pos -= 1 # go to previous element
|
||||
if pos < 0:
|
||||
return None
|
||||
return self[pos]
|
||||
|
||||
|
||||
def _get_item(self, index):
|
||||
ea = self._addrs[index]
|
||||
return (ea, self._names[ea], index)
|
||||
|
||||
|
||||
def __iter__(self):
|
||||
return (self._get_item(index) for index in xrange(0, len(self._addrs)))
|
||||
|
||||
|
||||
def __getitem__(self, index):
|
||||
"""Returns the tupple (ea, name, index)"""
|
||||
if index > len(self._addrs):
|
||||
raise StopIteration
|
||||
return self._get_item(index)
|
||||
|
||||
#</pycode(py_name)>
|
||||
%}
|
||||
%include "name.hpp"
|
||||
|
12
swig/pro.i
12
swig/pro.i
@ -83,7 +83,17 @@
|
||||
%ignore get_process_exit_code;
|
||||
%ignore BELOW_NORMAL_PRIORITY_CLASS;
|
||||
%ignore parse_command_line;
|
||||
%rename (parse_command_line) py_parse_command_line;
|
||||
%ignore parse_command_line2;
|
||||
%rename (parse_command_line2) py_parse_command_line;
|
||||
%ignore qgetenv;
|
||||
%ignore qsetenv;
|
||||
%ignore qctime;
|
||||
%ignore qlocaltime;
|
||||
%ignore qstrftime;
|
||||
%ignore qstrftime64;
|
||||
%ignore qstrtok;
|
||||
%ignore qstrlwr;
|
||||
%ignore qstrupr;
|
||||
%include "pro.h"
|
||||
|
||||
SWIG_DECLARE_PY_CLINKED_OBJECT(qstrvec_t)
|
||||
|
@ -87,6 +87,7 @@
|
||||
%ignore decorate_name;
|
||||
%ignore gen_decorate_name;
|
||||
%ignore calc_bare_name;
|
||||
%ignore calc_cpp_name;
|
||||
%ignore predicate_t;
|
||||
%ignore choose_named_type;
|
||||
%ignore get_default_align;
|
||||
@ -131,6 +132,14 @@
|
||||
|
||||
%ignore type_pair_vec_t::add_names;
|
||||
|
||||
%ignore format_data_info_t;
|
||||
%ignore valinfo_t;
|
||||
%ignore print_c_data;
|
||||
%ignore format_c_data;
|
||||
%ignore format_c_number;
|
||||
%ignore get_enum_member_expr;
|
||||
%ignore extend_sign;
|
||||
|
||||
// Kernel-only symbols
|
||||
%ignore init_til;
|
||||
%ignore save_til;
|
||||
@ -161,6 +170,7 @@
|
||||
|
||||
%rename (load_til) load_til_wrap;
|
||||
%rename (get_type_size0) py_get_type_size0;
|
||||
%rename (idc_get_type_raw) py_idc_get_type_raw;
|
||||
%rename (unpack_object_from_idb) py_unpack_object_from_idb;
|
||||
%rename (unpack_object_from_bv) py_unpack_object_from_bv;
|
||||
%rename (pack_object_to_idb) py_pack_object_to_idb;
|
||||
@ -266,12 +276,12 @@ PyObject *py_unpack_object_from_idb(
|
||||
p_list *fields = (p_list *) PyString_AsString(py_fields);
|
||||
idc_value_t idc_obj;
|
||||
error_t err = unpack_object_from_idb(
|
||||
&idc_obj,
|
||||
ti,
|
||||
type,
|
||||
fields,
|
||||
ea,
|
||||
NULL,
|
||||
&idc_obj,
|
||||
ti,
|
||||
type,
|
||||
fields,
|
||||
ea,
|
||||
NULL,
|
||||
pio_flags);
|
||||
|
||||
// Unpacking failed?
|
||||
@ -281,7 +291,7 @@ PyObject *py_unpack_object_from_idb(
|
||||
// Convert
|
||||
PyObject *py_ret(NULL);
|
||||
err = idcvar_to_pyvar(idc_obj, &py_ret);
|
||||
|
||||
|
||||
// Conversion failed?
|
||||
if ( err != CIP_OK )
|
||||
return Py_BuildValue("(ii)", 0, err);
|
||||
@ -334,11 +344,11 @@ PyObject *py_unpack_object_from_bv(
|
||||
|
||||
idc_value_t idc_obj;
|
||||
error_t err = unpack_object_from_bv(
|
||||
&idc_obj,
|
||||
ti,
|
||||
type,
|
||||
fields,
|
||||
bytes,
|
||||
&idc_obj,
|
||||
ti,
|
||||
type,
|
||||
fields,
|
||||
bytes,
|
||||
pio_flags);
|
||||
|
||||
// Unpacking failed?
|
||||
@ -519,6 +529,19 @@ int idc_parse_types(const char *input, int flags)
|
||||
return parse_decls(idati, input, (flags & 2) == 0 ? msg : NULL, hti);
|
||||
}
|
||||
|
||||
PyObject *py_idc_get_type_raw(ea_t ea)
|
||||
{
|
||||
qtype type, fields;
|
||||
if (get_tinfo(ea, &type, &fields))
|
||||
{
|
||||
return Py_BuildValue("(ss)", (char *)type.c_str(), (char *)fields.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
char *idc_get_type(ea_t ea, char *buf, size_t bufsize)
|
||||
{
|
||||
qtype type, fnames;
|
||||
|
@ -5,6 +5,7 @@
|
||||
#
|
||||
import glob
|
||||
import sys
|
||||
import os
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
def extract_docs(lines, out):
|
||||
@ -67,17 +68,29 @@ def extract_docs(lines, out):
|
||||
elif line == S_INLINE:
|
||||
in_inline = True
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
def gen_docs_from(file, out):
|
||||
f = open(file, 'r')
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
extract_docs(lines, out)
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
def gen_docs(path = '../swig/', outfn = 'idaapi.py', mask = '*.i'):
|
||||
out = []
|
||||
|
||||
# idaapi contains definitions used by other modules
|
||||
# handle it first
|
||||
idaapi_i = os.path.join(path, 'idaapi.i')
|
||||
gen_docs_from(idaapi_i, out)
|
||||
|
||||
for fn in glob.glob(path + mask):
|
||||
f = open(fn, 'r')
|
||||
lines = f.readlines()
|
||||
f.close()
|
||||
extract_docs(lines, out)
|
||||
fn = fn.replace('\\', '/')
|
||||
if fn != idaapi_i:
|
||||
gen_docs_from(fn, 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('"""This is a placeholder module used to document all the IDA SDK functions that are wrapped manually. You still need to import \'idaapi\' (not this module) to use the functions"""\n')
|
||||
f.write('\n'.join(out))
|
||||
f.close()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user