Skip to content
This repository was archived by the owner on Dec 24, 2025. It is now read-only.

Commit 69d5c83

Browse files
author
elias.bachaalany
committed
- 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
1 parent 4d21b10 commit 69d5c83

31 files changed

Lines changed: 902 additions & 580 deletions

CHANGES.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
Please see http://code.google.com/p/idapython/source/list for a detailed list of changes.
22

3+
Changes from version 1.5.4 to 1.5.5
4+
------------------------------------
5+
- IDA Pro 6.3 support
6+
- The Functions() generator function now accepts function tail start parameter
7+
- Added into idc.py: DbgRead/DbgWrite/SetTargetAssembler and stack pointer related functions
8+
- Wrapped more type info related functions
39

410
Changes from version 1.5.3 to 1.5.4
511
------------------------------------

build.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
VERBOSE = True
2525

2626
IDA_MAJOR_VERSION = 6
27-
IDA_MINOR_VERSION = 2
27+
IDA_MINOR_VERSION = 3
2828

2929
if 'IDA' in os.environ:
3030
IDA_SDK = os.environ['IDA']
@@ -36,7 +36,7 @@
3636
# IDAPython version
3737
VERSION_MAJOR = 1
3838
VERSION_MINOR = 5
39-
VERSION_PATCH = 4
39+
VERSION_PATCH = 5
4040

4141
# Determine Python version
4242
PYTHON_MAJOR_VERSION = int(platform.python_version()[0])
@@ -319,10 +319,11 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
319319
builder = GCCBuilder()
320320
platform_macros = [ "__LINUX__" ]
321321
python_libpath = os.path.join(sysconfig.EXEC_PREFIX, "lib")
322-
python_library = "-lpython%d.%d" % (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION)
322+
python_library = "-Bdynamic -lpython%d.%d" % (PYTHON_MAJOR_VERSION, PYTHON_MINOR_VERSION)
323323
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_linux_gcc_64" or "x86_linux_gcc_32")
324324
ida_lib = ""
325-
extra_link_parameters = ""
325+
extra_link_parameters = " -s"
326+
builder.compiler_parameters += " -O2"
326327
# Platform-specific settings for the Windows build
327328
elif platform == "win32":
328329
builder = MSVCBuilder()
@@ -333,6 +334,7 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
333334
ida_lib = "ida.lib"
334335
SWIG_OPTIONS += " -D__NT__ "
335336
extra_link_parameters = ""
337+
builder.compiler_parameters += " -Ox"
336338
# Platform-specific settings for the Mac OS X build
337339
elif platform == "macosx":
338340
builder = GCCBuilder()
@@ -342,14 +344,17 @@ def build_plugin(platform, idasdkdir, plugin_name, ea64):
342344
python_library = "-framework Python"
343345
ida_libpath = os.path.join(idasdkdir, "lib", ea64 and "x86_mac_gcc_64" or "x86_mac_gcc_32")
344346
ida_lib = ea64 and "-lida64" or "-lida"
345-
extra_link_parameters = ""
347+
extra_link_parameters = " -s"
348+
builder.compiler_parameters += " -O3"
346349

347350
assert builder, "Unknown platform! No idea how to build here..."
348351

349352
# Enable EA64 for the compiler if necessary
350353
if ea64:
351354
platform_macros.append("__EA64__")
352355

356+
platform_macros.append("NDEBUG")
357+
353358
if not '--no-early-load' in sys.argv:
354359
platform_macros.append("PLUGINFIX")
355360

examples/ex_expr.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
# -----------------------------------------------------------------------
2-
# This is an example illustrating how to extend IDC from Python
3-
# (c) Hex-Rays
4-
#
5-
from idaapi import set_idc_func_ex
6-
7-
#<pycode(ex_expr)>
8-
def py_power(n, e):
9-
return n ** e
10-
11-
ok = set_idc_func_ex("pow", py_power, (idaapi.VT_LONG, idaapi.VT_LONG), 0)
12-
if ok:
13-
print("Now the pow() will be present IDC!")
14-
else:
15-
print("Failed to register pow() IDC function")
16-
#</pycode(ex_expr)>
1+
# -----------------------------------------------------------------------
2+
# This is an example illustrating how to extend IDC from Python
3+
# (c) Hex-Rays
4+
#
5+
from idaapi import set_idc_func_ex
6+
7+
#<pycode(ex_expr)>
8+
def py_power(n, e):
9+
return n ** e
10+
11+
ok = set_idc_func_ex("pow", py_power, (idaapi.VT_LONG, idaapi.VT_LONG), 0)
12+
if ok:
13+
print("Now the pow() will be present IDC!")
14+
else:
15+
print("Failed to register pow() IDC function")
16+
#</pycode(ex_expr)>

python.cfg

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@ REMOVE_CWD_SYS_PATH = 0
88
// Script timeout (in seconds)
99
// (A value of 0 disables the timeout)
1010
SCRIPT_TIMEOUT = 3
11+
12+
// Use a local Python library
13+
// If enabled, the "lib" directory tree with modules must be present in IDADIR/python
14+
USE_LOCAL_PYTHON = 0

python.cpp

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ static int script_timeout = 2;
125125
static bool g_ui_ready = false;
126126
static bool g_alert_auto_scripts = true;
127127
static bool g_remove_cwd_sys_path = false;
128+
static bool g_use_local_python = false;
128129

129130
static void end_execution();
130131
static void begin_execution();
@@ -369,6 +370,11 @@ const char *idaapi set_python_options(
369370
g_remove_cwd_sys_path = *(uval_t *)value != 0;
370371
break;
371372
}
373+
else if ( qstrcmp(keyword, "USE_LOCAL_PYTHON") == 0 )
374+
{
375+
g_use_local_python = *(uval_t *)value != 0;
376+
break;
377+
}
372378
}
373379
return IDPOPT_BADKEY;
374380
} while (false);
@@ -466,7 +472,10 @@ static bool IDAPython_ExecFile(const char *FileName, char *errbuf, size_t errbuf
466472
{
467473
PyObject *py_execscript = get_idaapi_attr(S_IDAAPI_EXECSCRIPT);
468474
if ( py_execscript == NULL )
475+
{
476+
qstrncpy(errbuf, "Could not find idaapi." S_IDAAPI_EXECSCRIPT " ?!", errbufsz);
469477
return false;
478+
}
470479

471480
char script[MAXSTR];
472481
qstrncpy(script, FileName, sizeof(script));
@@ -1288,6 +1297,25 @@ static void sanitize_path()
12881297
PySys_SetPath(newpath.begin());
12891298
}
12901299

1300+
1301+
//-------------------------------------------------------------------------
1302+
// we have to do it ourselves because Python 2.7 calls exit() if importing site fails
1303+
static bool initsite(void)
1304+
{
1305+
PyObject *m;
1306+
m = PyImport_ImportModule("site");
1307+
if (m == NULL)
1308+
{
1309+
PyErr_Print();
1310+
Py_Finalize();
1311+
return false;
1312+
}
1313+
else {
1314+
Py_DECREF(m);
1315+
}
1316+
return true;
1317+
}
1318+
12911319
//-------------------------------------------------------------------------
12921320
// Initialize the Python environment
12931321
bool IDAPython_Init(void)
@@ -1306,12 +1334,11 @@ bool IDAPython_Init(void)
13061334
char tmp[QMAXPATH];
13071335
#ifdef __LINUX__
13081336
// Export symbols from libpython to resolve imported module deps
1309-
qsnprintf(tmp, sizeof(tmp), "libpython%d.%d.so.1",
1310-
PY_MAJOR_VERSION,
1311-
PY_MINOR_VERSION);
1312-
if ( !dlopen(tmp, RTLD_NOLOAD | RTLD_GLOBAL | RTLD_LAZY) )
1337+
// use the standard soname: libpython2.7.so.1.0
1338+
#define PYLIB "libpython" QSTRINGIZE(PY_MAJOR_VERSION) "." QSTRINGIZE(PY_MINOR_VERSION) ".so.1.0"
1339+
if ( !dlopen(PYLIB, RTLD_NOLOAD | RTLD_GLOBAL | RTLD_LAZY) )
13131340
{
1314-
warning("IDAPython: %s", dlerror());
1341+
warning("IDAPython dlopen(" PYLIB ") error: %s", dlerror());
13151342
return false;
13161343
}
13171344
#endif
@@ -1350,16 +1377,31 @@ bool IDAPython_Init(void)
13501377
}
13511378
}
13521379

1380+
if ( g_use_local_python )
1381+
Py_SetPythonHome(g_idapython_dir);
1382+
1383+
// don't import "site" right now
1384+
Py_NoSiteFlag = 1;
1385+
13531386
// Start the interpreter
13541387
Py_Initialize();
1388+
13551389
if ( !Py_IsInitialized() )
13561390
{
13571391
warning("IDAPython: Py_Initialize() failed");
13581392
return false;
13591393
}
13601394

1395+
// remove current directory
13611396
sanitize_path();
13621397

1398+
// import "site"
1399+
if ( !g_use_local_python && !initsite() )
1400+
{
1401+
warning("IDAPython: importing \"site\" failed");
1402+
return false;
1403+
}
1404+
13631405
// Enable multi-threading support
13641406
if ( !PyEval_ThreadsInitialized() )
13651407
PyEval_InitThreads();
@@ -1416,7 +1458,7 @@ bool IDAPython_Init(void)
14161458
parse_plugin_options();
14171459

14181460
// Register a RunPythonStatement() function for IDC
1419-
set_idc_func(S_IDC_RUNPYTHON_STATEMENT, idc_runpythonstatement, idc_runpythonstatement_args);
1461+
set_idc_func_ex(S_IDC_RUNPYTHON_STATEMENT, idc_runpythonstatement, idc_runpythonstatement_args, 0);
14201462

14211463
// A script specified on the command line is run
14221464
if ( g_run_when == run_on_init )
@@ -1463,7 +1505,7 @@ void IDAPython_Term(void)
14631505
deinit_pywraps();
14641506

14651507
// Uninstall IDC function
1466-
set_idc_func(S_IDC_RUNPYTHON_STATEMENT, NULL, NULL);
1508+
set_idc_func_ex(S_IDC_RUNPYTHON_STATEMENT, NULL, NULL, 0);
14671509

14681510
// Shut the interpreter down
14691511
Py_Finalize();

python/idautils.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,14 @@ def Functions(start=None, end=None):
217217
if not start: start = idaapi.cvar.inf.minEA
218218
if not end: end = idaapi.cvar.inf.maxEA
219219

220-
func = idaapi.get_func(start)
221-
if not func:
222-
func = idaapi.get_next_func(start)
220+
# find first function head chunk in the range
221+
chunk = idaapi.get_fchunk(start)
222+
if not chunk:
223+
chunk = idaapi.get_next_fchunk(start)
224+
while chunk and chunk.startEA < end and (chunk.flags & idaapi.FUNC_TAIL) != 0:
225+
chunk = idaapi.get_next_fchunk(chunk.startEA)
226+
func = chunk
227+
223228
while func and func.startEA < end:
224229
startea = func.startEA
225230
yield startea

0 commit comments

Comments
 (0)