- 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:
elias.bachaalany 2012-06-24 20:49:11 +00:00
parent 4d21b10dc4
commit 69d5c83d28
31 changed files with 908 additions and 586 deletions

View File

@ -1,5 +1,11 @@
Please see http://code.google.com/p/idapython/source/list for a detailed list of changes. 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 Changes from version 1.5.3 to 1.5.4
------------------------------------ ------------------------------------

View File

@ -24,7 +24,7 @@ from distutils import sysconfig
VERBOSE = True VERBOSE = True
IDA_MAJOR_VERSION = 6 IDA_MAJOR_VERSION = 6
IDA_MINOR_VERSION = 2 IDA_MINOR_VERSION = 3
if 'IDA' in os.environ: if 'IDA' in os.environ:
IDA_SDK = os.environ['IDA'] IDA_SDK = os.environ['IDA']
@ -36,7 +36,7 @@ else:
# IDAPython version # IDAPython version
VERSION_MAJOR = 1 VERSION_MAJOR = 1
VERSION_MINOR = 5 VERSION_MINOR = 5
VERSION_PATCH = 4 VERSION_PATCH = 5
# Determine Python version # Determine Python version
PYTHON_MAJOR_VERSION = int(platform.python_version()[0]) PYTHON_MAJOR_VERSION = int(platform.python_version()[0])
@ -319,10 +319,11 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
builder = GCCBuilder() builder = GCCBuilder()
platform_macros = [ "__LINUX__" ] platform_macros = [ "__LINUX__" ]
python_libpath = os.path.join(sysconfig.EXEC_PREFIX, "lib") 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_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_linux_gcc_64" or "x86_linux_gcc_32")
ida_lib = "" ida_lib = ""
extra_link_parameters = "" extra_link_parameters = " -s"
builder.compiler_parameters += " -O2"
# Platform-specific settings for the Windows build # Platform-specific settings for the Windows build
elif platform == "win32": elif platform == "win32":
builder = MSVCBuilder() builder = MSVCBuilder()
@ -333,6 +334,7 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
ida_lib = "ida.lib" ida_lib = "ida.lib"
SWIG_OPTIONS += " -D__NT__ " SWIG_OPTIONS += " -D__NT__ "
extra_link_parameters = "" extra_link_parameters = ""
builder.compiler_parameters += " -Ox"
# Platform-specific settings for the Mac OS X build # Platform-specific settings for the Mac OS X build
elif platform == "macosx": elif platform == "macosx":
builder = GCCBuilder() builder = GCCBuilder()
@ -342,7 +344,8 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
python_library = "-framework Python" python_library = "-framework Python"
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_mac_gcc_64" or "x86_mac_gcc_32") 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" 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..." assert builder, "Unknown platform! No idea how to build here..."
@ -350,6 +353,8 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
if ea64: if ea64:
platform_macros.append("__EA64__") platform_macros.append("__EA64__")
platform_macros.append("NDEBUG")
if not '--no-early-load' in sys.argv: if not '--no-early-load' in sys.argv:
platform_macros.append("PLUGINFIX") platform_macros.append("PLUGINFIX")

View File

@ -8,3 +8,7 @@ REMOVE_CWD_SYS_PATH = 0
// Script timeout (in seconds) // Script timeout (in seconds)
// (A value of 0 disables the timeout) // (A value of 0 disables the timeout)
SCRIPT_TIMEOUT = 3 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

View File

@ -125,6 +125,7 @@ static int script_timeout = 2;
static bool g_ui_ready = false; static bool g_ui_ready = false;
static bool g_alert_auto_scripts = true; static bool g_alert_auto_scripts = true;
static bool g_remove_cwd_sys_path = false; static bool g_remove_cwd_sys_path = false;
static bool g_use_local_python = false;
static void end_execution(); static void end_execution();
static void begin_execution(); static void begin_execution();
@ -369,6 +370,11 @@ const char *idaapi set_python_options(
g_remove_cwd_sys_path = *(uval_t *)value != 0; g_remove_cwd_sys_path = *(uval_t *)value != 0;
break; break;
} }
else if ( qstrcmp(keyword, "USE_LOCAL_PYTHON") == 0 )
{
g_use_local_python = *(uval_t *)value != 0;
break;
}
} }
return IDPOPT_BADKEY; return IDPOPT_BADKEY;
} while (false); } 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); PyObject *py_execscript = get_idaapi_attr(S_IDAAPI_EXECSCRIPT);
if ( py_execscript == NULL ) if ( py_execscript == NULL )
{
qstrncpy(errbuf, "Could not find idaapi." S_IDAAPI_EXECSCRIPT " ?!", errbufsz);
return false; return false;
}
char script[MAXSTR]; char script[MAXSTR];
qstrncpy(script, FileName, sizeof(script)); qstrncpy(script, FileName, sizeof(script));
@ -1288,6 +1297,25 @@ static void sanitize_path()
PySys_SetPath(newpath.begin()); 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 // Initialize the Python environment
bool IDAPython_Init(void) bool IDAPython_Init(void)
@ -1306,12 +1334,11 @@ bool IDAPython_Init(void)
char tmp[QMAXPATH]; char tmp[QMAXPATH];
#ifdef __LINUX__ #ifdef __LINUX__
// Export symbols from libpython to resolve imported module deps // Export symbols from libpython to resolve imported module deps
qsnprintf(tmp, sizeof(tmp), "libpython%d.%d.so.1", // use the standard soname: libpython2.7.so.1.0
PY_MAJOR_VERSION, #define PYLIB "libpython" QSTRINGIZE(PY_MAJOR_VERSION) "." QSTRINGIZE(PY_MINOR_VERSION) ".so.1.0"
PY_MINOR_VERSION); if ( !dlopen(PYLIB, RTLD_NOLOAD | RTLD_GLOBAL | RTLD_LAZY) )
if ( !dlopen(tmp, RTLD_NOLOAD | RTLD_GLOBAL | RTLD_LAZY) )
{ {
warning("IDAPython: %s", dlerror()); warning("IDAPython dlopen(" PYLIB ") error: %s", dlerror());
return false; return false;
} }
#endif #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 // Start the interpreter
Py_Initialize(); Py_Initialize();
if ( !Py_IsInitialized() ) if ( !Py_IsInitialized() )
{ {
warning("IDAPython: Py_Initialize() failed"); warning("IDAPython: Py_Initialize() failed");
return false; return false;
} }
// remove current directory
sanitize_path(); sanitize_path();
// import "site"
if ( !g_use_local_python && !initsite() )
{
warning("IDAPython: importing \"site\" failed");
return false;
}
// Enable multi-threading support // Enable multi-threading support
if ( !PyEval_ThreadsInitialized() ) if ( !PyEval_ThreadsInitialized() )
PyEval_InitThreads(); PyEval_InitThreads();
@ -1416,7 +1458,7 @@ bool IDAPython_Init(void)
parse_plugin_options(); parse_plugin_options();
// Register a RunPythonStatement() function for IDC // 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 // A script specified on the command line is run
if ( g_run_when == run_on_init ) if ( g_run_when == run_on_init )
@ -1463,7 +1505,7 @@ void IDAPython_Term(void)
deinit_pywraps(); deinit_pywraps();
// Uninstall IDC function // 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 // Shut the interpreter down
Py_Finalize(); Py_Finalize();

View File

@ -217,9 +217,14 @@ def Functions(start=None, end=None):
if not start: start = idaapi.cvar.inf.minEA if not start: start = idaapi.cvar.inf.minEA
if not end: end = idaapi.cvar.inf.maxEA if not end: end = idaapi.cvar.inf.maxEA
func = idaapi.get_func(start) # find first function head chunk in the range
if not func: chunk = idaapi.get_fchunk(start)
func = idaapi.get_next_func(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: while func and func.startEA < end:
startea = func.startEA startea = func.startEA
yield startea yield startea

View File

@ -1772,6 +1772,35 @@ def DbgQword(ea):
return __DbgValue(ea, 8) 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): def GetOriginalByte(ea):
""" """
Get original value of program byte Get original value of program byte
@ -2867,6 +2896,16 @@ def SetProcessorType (processor, level):
""" """
return idaapi.set_processor_type(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_COMPAT = idaapi.SETPROC_COMPAT
SETPROC_ALL = idaapi.SETPROC_ALL SETPROC_ALL = idaapi.SETPROC_ALL
SETPROC_USER = idaapi.SETPROC_USER SETPROC_USER = idaapi.SETPROC_USER
@ -4340,6 +4379,75 @@ def SetSpDiff(ea, delta):
return idaapi.add_user_stkpnt(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 # 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 @return: -1 - no fixup at the specified address
otherwise returns fixup target type: 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 -1
return fd.type return fd.type
@ -4504,8 +4612,12 @@ def GetFixupTgtSel(ea):
@return: -1 - no fixup at the specified address @return: -1 - no fixup at the specified address
otherwise returns fixup target selector otherwise returns fixup target selector
""" """
fd = idaapi.get_fixup(ea) fd = idaapi.fixup_data_t()
return -1 if not fd else fd.sel
if not idaapi.get_fixup(ea, fd):
return -1
return fd.sel
def GetFixupTgtOff(ea): def GetFixupTgtOff(ea):
@ -4517,8 +4629,12 @@ def GetFixupTgtOff(ea):
@return: -1 - no fixup at the specified address @return: -1 - no fixup at the specified address
otherwise returns fixup target offset otherwise returns fixup target offset
""" """
fd = idaapi.get_fixup(ea) fd = idaapi.fixup_data_t()
return -1 if not fd else fd.off
if not idaapi.get_fixup(ea, fd):
return -1
return fd.off
def GetFixupTgtDispl(ea): def GetFixupTgtDispl(ea):
@ -4530,8 +4646,12 @@ def GetFixupTgtDispl(ea):
@return: -1 - no fixup at the specified address @return: -1 - no fixup at the specified address
otherwise returns fixup target displacement otherwise returns fixup target displacement
""" """
fd = idaapi.get_fixup(ea) fd = idaapi.fixup_data_t()
return -1 if not fd else fd.displacement
if not idaapi.get_fixup(ea, fd):
return -1
return fd.displacement
def SetFixup(ea, fixuptype, targetsel, targetoff, displ): def SetFixup(ea, fixuptype, targetsel, targetoff, displ):
@ -4791,6 +4911,30 @@ def GetMemberQty(sid):
return -1 if not s else s.memqty 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): def GetStrucPrevOff(sid, offset):
""" """
Get previous offset in a structure Get previous offset in a structure
@ -6633,6 +6777,15 @@ def SizeOf(typestr):
""" """
return idaapi.get_type_size0(idaapi.cvar.idati, 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): def GuessType(ea):
""" """
Guess type of function/variable Guess type of function/variable
@ -6652,11 +6805,16 @@ def SetType(ea, newtype):
@param newtype: the type string in C declaration form. @param newtype: the type string in C declaration form.
Must contain the closing ';' Must contain the closing ';'
if specified as an empty string, then the 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: 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): def ParseType(inputtype, flags):
""" """
@ -7680,6 +7838,29 @@ def SetBptAttr(address, bptattr, value):
idaapi.update_bpt(bpt) idaapi.update_bpt(bpt)
return True 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): def SetBptCnd(ea, cnd):
""" """
@ -7690,14 +7871,7 @@ def SetBptCnd(ea, cnd):
@return: success @return: success
""" """
bpt = idaapi.bpt_t() return SetBptCndEx(ea, cnd, 0)
if not idaapi.get_bpt(ea, bpt):
return False
bpt.condition = cnd
return idaapi.update_bpt(bpt)
def AddBptEx(ea, size, bpttype): def AddBptEx(ea, size, bpttype):

View File

@ -68,6 +68,8 @@ def print_banner():
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------
# Redirect stderr and stdout to the IDA message window # Redirect stderr and stdout to the IDA message window
_orig_stdout = sys.stdout;
_orig_stderr = sys.stderr;
sys.stdout = sys.stderr = IDAPythonStdOut() sys.stdout = sys.stderr = IDAPythonStdOut()
# Assign a default sys.argv # Assign a default sys.argv

View File

@ -3,7 +3,7 @@
rem Please use the same tag for the same .i file 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 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.
echo -------- DEPLOY started -------------------------------------------------- echo -------- DEPLOY started --------------------------------------------------

View File

@ -168,5 +168,5 @@ plugin_t PLUGIN =
"", // multiline help about the plugin "", // multiline help about the plugin
"pywraps", // the preferred short name of 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
}; };

View File

@ -571,6 +571,14 @@ def test_gpa():
return 1 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 # Packs a simple structure (into the database) and unpacks it back using the idaapi methods
def test_pck_idb_raw(): def test_pck_idb_raw():
@ -884,7 +892,7 @@ def test_exec_throw():
# all the tests that take zero parameters # all the tests that take zero parameters
tests0 = (test_gpa, test_pck_idb_raw, test_pck_bv_raw, tests0 = (test_gpa, test_pck_idb_raw, test_pck_bv_raw,
test_unpack_raw, test_pck_idb, test_pck_bv, 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 test_log = None # test log file
# ----------------------------------------------------------------------- # -----------------------------------------------------------------------

View File

@ -152,6 +152,16 @@ static PyObject *py_get_many_bytes(ea_t ea, unsigned int size)
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
/* /*
#<pydoc> #<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): def get_ascii_contents2(ea, len, type, flags = ACFOPT_ASCII):
""" """
Get contents of ascii string Get contents of ascii string

View File

@ -562,7 +562,7 @@ private:
void show() 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) static py_graph_t *extract_this(PyObject *self)
@ -666,7 +666,7 @@ private:
qsnprintf(grnode, sizeof(grnode), "$ pygraph %s", title); qsnprintf(grnode, sizeof(grnode), "$ pygraph %s", title);
id.create(grnode); id.create(grnode);
gv = create_graph_viewer(form, id, s_callback, this, 0); 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 ) if ( gv != NULL )
viewer_fit_window(gv); viewer_fit_window(gv);
} }

View File

@ -619,7 +619,7 @@ def parse_command_line(cmdline):
static PyObject *py_parse_command_line(const char *cmdline) static PyObject *py_parse_command_line(const char *cmdline)
{ {
qstrvec_t args; qstrvec_t args;
if ( parse_command_line(cmdline, &args) == 0 ) if ( parse_command_line2(cmdline, &args, NULL) == 0 )
Py_RETURN_NONE; Py_RETURN_NONE;
PyObject *py_list = PyList_New(args.size()); PyObject *py_list = PyList_New(args.size());

View File

@ -434,7 +434,7 @@ class IDP_Hooks(object):
- cmd.itype must be set >= idaapi.CUSTOM_CMD_ITYPE - cmd.itype must be set >= idaapi.CUSTOM_CMD_ITYPE
- cmd.size must be set to the instruction length - cmd.size must be set to the instruction length
@return: Boolean @return: Boolean
- False if the instruction is not recognized - False if the instruction is not recognized
- True if the instruction was decoded. idaapi.cmd should be filled in that case. - True if the instruction was decoded. idaapi.cmd should be filled in that case.
""" """

View File

@ -494,7 +494,7 @@ in this case.
This flag can be used to delay the code execution This flag can be used to delay the code execution
until the next UI loop run even from the main thread""" 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. Executes a function in the context of the main thread.
If the current thread not the main thread, then the call is queued and 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> #<pydoc>
def execute_ui_requests(callable_list) def execute_ui_requests(callable_list):
""" """
Inserts a list of callables into the UI message processing queue. Inserts a list of callables into the UI message processing queue.
When the UI is ready it will call one callable. 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. IDA is terminated and the database is already closed.
The UI may close its windows in this callback. 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> #</pydoc>
*/ */
@ -769,6 +773,7 @@ class UI_Hooks
public: public:
virtual ~UI_Hooks() virtual ~UI_Hooks()
{ {
unhook();
} }
bool hook() bool hook()

View File

@ -139,7 +139,7 @@ static bool plgform_show(
PyObject *py_link, PyObject *py_link,
PyObject *py_obj, PyObject *py_obj,
const char *caption, const char *caption,
int options = FORM_MDI|FORM_TAB|FORM_MENU|FORM_RESTORE) int options = FORM_TAB|FORM_MENU|FORM_RESTORE)
{ {
DECL_PLGFORM; DECL_PLGFORM;
return plgform->show(py_obj, caption, options); return plgform->show(py_obj, caption, options);

View File

@ -9,7 +9,7 @@ class PluginForm(object):
""" """
FORM_MDI = 0x01 FORM_MDI = 0x01
"""start by default as MDI""" """start by default as MDI (obsolete)"""
FORM_TAB = 0x02 FORM_TAB = 0x02
"""attached by default to a tab""" """attached by default to a tab"""
FORM_RESTORE = 0x04 FORM_RESTORE = 0x04
@ -38,7 +38,7 @@ class PluginForm(object):
@param caption: The form caption @param caption: The form caption
@param options: One of PluginForm.FORM_ constants @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) return _idaapi.plgform_show(self.__clink__, self, caption, options)

View File

@ -11,6 +11,7 @@
%ignore auto_save; %ignore auto_save;
%ignore auto_term; %ignore auto_term;
%ignore ea_without_xrefs; %ignore ea_without_xrefs;
%ignore postpone_lastinsn_analysis;
%include "auto.hpp" %include "auto.hpp"

View File

@ -764,6 +764,16 @@ static PyObject *py_get_many_bytes(ea_t ea, unsigned int size)
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
/* /*
#<pydoc> #<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): def get_ascii_contents2(ea, len, type, flags = ACFOPT_ASCII):
""" """
Get contents of ascii string Get contents of ascii string

View File

@ -62,9 +62,8 @@ static ea_t get_fchunk_referer(ea_t ea, size_t idx)
def get_idasgn_desc(n): def get_idasgn_desc(n):
""" """
Get information about a signature in the list. Get information about a signature in the list.
It returns both: It returns both: the name of the signature, and names of the
signame - the name of the signature optional libraries
optlibs - the names of the optional libraries
@param n: number of signature in the list (0..get_idasgn_qty()-1) @param n: number of signature in the list (0..get_idasgn_qty()-1)
@return: None on failure or tuple(signame, optlibs) @return: None on failure or tuple(signame, optlibs)

View File

@ -564,7 +564,7 @@ private:
void show() 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) static py_graph_t *extract_this(PyObject *self)
@ -668,7 +668,7 @@ private:
qsnprintf(grnode, sizeof(grnode), "$ pygraph %s", title); qsnprintf(grnode, sizeof(grnode), "$ pygraph %s", title);
id.create(grnode); id.create(grnode);
gv = create_graph_viewer(form, id, s_callback, this, 0); 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 ) if ( gv != NULL )
viewer_fit_window(gv); viewer_fit_window(gv);
} }

View File

@ -15,7 +15,7 @@
%constant size_t SIZE_MAX = size_t(-1); %constant size_t SIZE_MAX = size_t(-1);
// Enable automatic docstring generation // Enable automatic docstring generation
%feature(autodoc); %feature(autodoc,0);
%define SWIG_DECLARE_PY_CLINKED_OBJECT(type) %define SWIG_DECLARE_PY_CLINKED_OBJECT(type)
%inline %{ %inline %{
@ -2694,7 +2694,7 @@ def parse_command_line(cmdline):
static PyObject *py_parse_command_line(const char *cmdline) static PyObject *py_parse_command_line(const char *cmdline)
{ {
qstrvec_t args; qstrvec_t args;
if ( parse_command_line(cmdline, &args) == 0 ) if ( parse_command_line2(cmdline, &args, NULL) == 0 )
Py_RETURN_NONE; Py_RETURN_NONE;
PyObject *py_list = PyList_New(args.size()); PyObject *py_list = PyList_New(args.size());

View File

@ -475,7 +475,7 @@ class IDP_Hooks(object):
- cmd.itype must be set >= idaapi.CUSTOM_CMD_ITYPE - cmd.itype must be set >= idaapi.CUSTOM_CMD_ITYPE
- cmd.size must be set to the instruction length - cmd.size must be set to the instruction length
@return: Boolean @return: Boolean
- False if the instruction is not recognized - False if the instruction is not recognized
- True if the instruction was decoded. idaapi.cmd should be filled in that case. - True if the instruction was decoded. idaapi.cmd should be filled in that case.
""" """

View File

@ -619,7 +619,7 @@ in this case.
This flag can be used to delay the code execution This flag can be used to delay the code execution
until the next UI loop run even from the main thread""" 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. Executes a function in the context of the main thread.
If the current thread not the main thread, then the call is queued and 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> #<pydoc>
def execute_ui_requests(callable_list) def execute_ui_requests(callable_list):
""" """
Inserts a list of callables into the UI message processing queue. Inserts a list of callables into the UI message processing queue.
When the UI is ready it will call one callable. 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. IDA is terminated and the database is already closed.
The UI may close its windows in this callback. 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> #</pydoc>
*/ */
@ -894,6 +898,7 @@ class UI_Hooks
public: public:
virtual ~UI_Hooks() virtual ~UI_Hooks()
{ {
unhook();
} }
bool hook() bool hook()
@ -2807,7 +2812,7 @@ static bool plgform_show(
PyObject *py_link, PyObject *py_link,
PyObject *py_obj, PyObject *py_obj,
const char *caption, const char *caption,
int options = FORM_MDI|FORM_TAB|FORM_MENU|FORM_RESTORE) int options = FORM_TAB|FORM_MENU|FORM_RESTORE)
{ {
DECL_PLGFORM; DECL_PLGFORM;
return plgform->show(py_obj, caption, options); return plgform->show(py_obj, caption, options);
@ -5531,7 +5536,7 @@ class PluginForm(object):
""" """
FORM_MDI = 0x01 FORM_MDI = 0x01
"""start by default as MDI""" """start by default as MDI (obsolete)"""
FORM_TAB = 0x02 FORM_TAB = 0x02
"""attached by default to a tab""" """attached by default to a tab"""
FORM_RESTORE = 0x04 FORM_RESTORE = 0x04
@ -5560,7 +5565,7 @@ class PluginForm(object):
@param caption: The form caption @param caption: The form caption
@param options: One of PluginForm.FORM_ constants @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) return _idaapi.plgform_show(self.__clink__, self, caption, options)

View File

@ -83,7 +83,17 @@
%ignore get_process_exit_code; %ignore get_process_exit_code;
%ignore BELOW_NORMAL_PRIORITY_CLASS; %ignore BELOW_NORMAL_PRIORITY_CLASS;
%ignore parse_command_line; %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" %include "pro.h"
SWIG_DECLARE_PY_CLINKED_OBJECT(qstrvec_t) SWIG_DECLARE_PY_CLINKED_OBJECT(qstrvec_t)

View File

@ -87,6 +87,7 @@
%ignore decorate_name; %ignore decorate_name;
%ignore gen_decorate_name; %ignore gen_decorate_name;
%ignore calc_bare_name; %ignore calc_bare_name;
%ignore calc_cpp_name;
%ignore predicate_t; %ignore predicate_t;
%ignore choose_named_type; %ignore choose_named_type;
%ignore get_default_align; %ignore get_default_align;
@ -131,6 +132,14 @@
%ignore type_pair_vec_t::add_names; %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 // Kernel-only symbols
%ignore init_til; %ignore init_til;
%ignore save_til; %ignore save_til;
@ -161,6 +170,7 @@
%rename (load_til) load_til_wrap; %rename (load_til) load_til_wrap;
%rename (get_type_size0) py_get_type_size0; %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_idb) py_unpack_object_from_idb;
%rename (unpack_object_from_bv) py_unpack_object_from_bv; %rename (unpack_object_from_bv) py_unpack_object_from_bv;
%rename (pack_object_to_idb) py_pack_object_to_idb; %rename (pack_object_to_idb) py_pack_object_to_idb;
@ -519,6 +529,19 @@ int idc_parse_types(const char *input, int flags)
return parse_decls(idati, input, (flags & 2) == 0 ? msg : NULL, hti); 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) char *idc_get_type(ea_t ea, char *buf, size_t bufsize)
{ {
qtype type, fnames; qtype type, fnames;

View File

@ -5,6 +5,7 @@
# #
import glob import glob
import sys import sys
import os
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def extract_docs(lines, out): def extract_docs(lines, out):
@ -67,17 +68,29 @@ def extract_docs(lines, out):
elif line == S_INLINE: elif line == S_INLINE:
in_inline = True 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'): def gen_docs(path = '../swig/', outfn = 'idaapi.py', mask = '*.i'):
out = [] 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): for fn in glob.glob(path + mask):
f = open(fn, 'r') fn = fn.replace('\\', '/')
lines = f.readlines() if fn != idaapi_i:
f.close() gen_docs_from(fn, out)
extract_docs(lines, out)
f = open(outfn, 'w') 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.write('\n'.join(out))
f.close() f.close()