mirror of
https://github.com/idapython/src
synced 2026-06-08 14:47:00 +00:00
158 lines
5.2 KiB
Python
158 lines
5.2 KiB
Python
"""
|
|
This script replaces the long sequence of calls like:
|
|
SWIG_Python_SetConstant(d, "s39_xg",SWIG_From_int(static_cast< int >(s39_xg)));
|
|
SWIG_Python_SetConstant(d, "s39_xgr",SWIG_From_int(static_cast< int >(s39_xgr)));
|
|
|
|
by a table of names+values and a loop calling the function.
|
|
|
|
This is necessitated by the huge slowdown in GCC when trying to optimize a huge list of such calls
|
|
in allins.cpp SWIG wrapper (~20 min).
|
|
|
|
"""
|
|
from __future__ import print_function
|
|
|
|
import re
|
|
from argparse import ArgumentParser
|
|
|
|
parser = ArgumentParser(description='Patch calling conventions for some functions, so it builds on windows')
|
|
parser.add_argument("-i", "--input", required=True)
|
|
parser.add_argument("-o", "--output", required=True)
|
|
parser.add_argument("-v", "--verbose", default=False, action="store_true")
|
|
args = parser.parse_args()
|
|
|
|
outlines = []
|
|
STAT_SEEKING = 1
|
|
STAT_ALMOST_THERE = 2
|
|
STAT_COLLECTING = 3
|
|
|
|
almost_there_re = re.compile(r"^\s+\*\s+Partial Init method.*")
|
|
start_collecting_re = re.compile(r"^#ifdef __cplusplus.*")
|
|
end_collecting_re = re.compile(r"^\s*/\* Initialize threading \*/")
|
|
|
|
# SWIG_Python_SetConstant(d, "BADADDR",SWIG_From_unsigned_SS_int(static_cast< unsigned int >(ea_t(-1))));
|
|
set_constant_re = re.compile(r"^\s*SWIG_Python_SetConstant\(\s*d\s*,([^,]*),(.*)\);$")
|
|
|
|
# Supported types we can simply expression for
|
|
# SWIG_From_int(static_cast< int >(0x00C0))
|
|
pyobj_expr_int = re.compile(r"SWIG_From_int\(static_cast<\s*int\s*>\((.*)\)\)")
|
|
# SWIG_From_unsigned_SS_int(static_cast< unsigned int >((1u << 16)))
|
|
pyobj_expr_uint = re.compile(r"SWIG_From_unsigned_SS_int\(static_cast<\s*unsigned\s+int\s*>\((.*)\)\)")
|
|
# SWIG_From_long(static_cast< long >(0x00002000L))
|
|
pyobj_expr_long = re.compile(r"SWIG_From_long\(static_cast<\s*long\s*>\((.*)\)\)")
|
|
# SWIG_From_unsigned_SS_long(static_cast< unsigned long >(0xF0000000LU))
|
|
pyobj_expr_ulong = re.compile(r"SWIG_From_unsigned_SS_long\(static_cast<\s*unsigned\s+long\s*>\((.*)\)\)")
|
|
# SWIG_FromCharPtr("\22")
|
|
pyobj_expr_str = re.compile(r"SWIG_FromCharPtr\((.*)\)")
|
|
|
|
|
|
status = STAT_SEEKING
|
|
class Foldable(object):
|
|
def __init__(self, re, enum, initializer, cast, replacement):
|
|
self.re = re
|
|
self.enum = enum
|
|
self.initializer = initializer
|
|
self.cast = cast
|
|
self.replacement = replacement
|
|
self.found_any = False
|
|
|
|
subexprs = {
|
|
"i" : Foldable(
|
|
pyobj_expr_int,
|
|
"cit_int",
|
|
"i",
|
|
"int",
|
|
"SWIG_From_int(static_cast< int >(ci.val))"),
|
|
}
|
|
|
|
def generate_constants(constants):
|
|
# now, generate the array & loop
|
|
outlines.append("""
|
|
/* 'SetConstant' replacement */
|
|
static const ida_local struct ci_t
|
|
{
|
|
const char *name;
|
|
int val;
|
|
} cis[%d] = {
|
|
""" % len(constants))
|
|
|
|
for c in constants:
|
|
name = c[0]
|
|
expr = c[1]
|
|
|
|
# Analyze expression. If it is one of the
|
|
# supported types, let's simplify the code.
|
|
for kind in ["i"]:
|
|
subexpr = subexprs[kind]
|
|
sematch = subexpr.re.search(expr)
|
|
if sematch:
|
|
citype = subexpr.enum
|
|
expr = sematch.group(1)
|
|
init = subexpr.initializer
|
|
cast = subexpr.cast
|
|
subexpr.found_any = True
|
|
break
|
|
outlines.append("\t{%s, static_cast< int >(%s)},\n" % (name, expr))
|
|
|
|
outlines.append("""
|
|
};
|
|
|
|
for ( size_t _cidx = 0; _cidx < qnumber(cis); ++_cidx )
|
|
{
|
|
const ci_t &ci = cis[_cidx];
|
|
PyObject *o = """)
|
|
|
|
subexpr = subexprs["i"]
|
|
outlines.append("""%s;""" % (subexpr.replacement))
|
|
|
|
outlines.append("""
|
|
SWIG_Python_SetConstant(d, ci.name, o);
|
|
}
|
|
""")
|
|
|
|
with open(args.input) as f:
|
|
constants = []
|
|
|
|
for line in f:
|
|
if status == STAT_SEEKING:
|
|
if almost_there_re.match(line):
|
|
status = STAT_ALMOST_THERE
|
|
if args.verbose:
|
|
print("Almost there at line: '%s'" % line)
|
|
outlines.append(line)
|
|
elif status == STAT_ALMOST_THERE:
|
|
if start_collecting_re.match(line):
|
|
status = STAT_COLLECTING
|
|
if args.verbose:
|
|
print("Starting to collect at line: '%s'" % line)
|
|
outlines.append("#ifdef __NT__\n")
|
|
outlines.append("#pragma warning(disable: 4883)\n")
|
|
outlines.append("#endif // __NT__\n")
|
|
outlines.append(line)
|
|
elif status == STAT_COLLECTING:
|
|
if end_collecting_re.match(line):
|
|
outlines.append(line)
|
|
|
|
if len(constants):
|
|
generate_constants(constants)
|
|
|
|
status = STAT_SEEKING
|
|
if args.verbose:
|
|
print("Done collecting at line: '%s'" % line)
|
|
else:
|
|
match = set_constant_re.search(line)
|
|
if match and pyobj_expr_int.search(match.group(2)):
|
|
tpl = (match.group(1), match.group(2))
|
|
constants.append(tpl)
|
|
if args.verbose:
|
|
print("Found 'SetConstant' expression: %s => %s" % tpl)
|
|
else:
|
|
outlines.append(line)
|
|
|
|
import tempfile
|
|
temp = tempfile.NamedTemporaryFile(mode="w", delete=False)
|
|
temp.write("".join(outlines))
|
|
temp.close()
|
|
|
|
import shutil
|
|
shutil.move(temp.name, args.output)
|