Files
idapython-src/tools/patch_codegen.py
T

74 lines
3.0 KiB
Python

import os, re
try:
from argparse import ArgumentParser
except:
print "Failed to import module 'argparse'. Upgrade to Python 2.7, copy argparse.py to this directory or try 'apt-get install python-argparse'"
raise
parser = ArgumentParser(description='Patch some code generation, so it builds')
parser.add_argument("-f", "--file", required=True)
parser.add_argument("-p", "--patches", required=True)
parser.add_argument("-v", "--verbose", default=False, action="store_true")
parser.add_argument("-V", "--apply-valist-patches", default=False, action="store_true")
args = parser.parse_args()
patched_cmt = "// patched by patch_codegen.py"
if os.path.isfile(args.patches):
with open(args.patches, "r") as fin:
patches = eval(fin.read())
wrap_regex = re.compile(r"SWIGINTERN PyObject \*_wrap_([a-zA-Z0-9_]*)\(.*")
director_method_regex = re.compile(r".*(SwigDirector_[a-zA-Z0-9_]*::[a-zA-Z0-9_]*)\(.*")
swig_clink_var_get_regex = re.compile(r"SWIGINTERN PyObject \*(Swig_var_[a-zA-Z0-9_]*_get).*")
swig_clink_var_set_regex = re.compile(r"SWIGINTERN int (Swig_var_[a-zA-Z0-9_]*_set).*")
lines = []
with open(args.file, "rb") as f:
STAT_UNKNOWN = {}
STAT_IN_FUNCTION = {}
stat = STAT_UNKNOWN
func_patches = []
entered_function = False
for line in f:
m = wrap_regex.match(line)
if not m:
m = director_method_regex.match(line)
if not m:
m = swig_clink_var_get_regex.match(line)
if not m:
m = swig_clink_var_set_regex.match(line)
if m:
stat = STAT_IN_FUNCTION
fname = m.group(1)
entered_function = True
func_patches = patches.get(fname, [])
else:
for patch_kind, patch_data in func_patches:
if patch_kind == "va_copy":
if args.apply_valist_patches:
dst_va, src_va = patch_data
target = "%s = *%s;" % (dst_va, src_va)
if line.strip() == target:
line = "set_vva(%s, *%s); %s\n" % (dst_va, src_va, patched_cmt)
elif patch_kind == "acquire_gil":
if entered_function:
line = " PYW_GIL_GET; %s\n%s" % (patched_cmt, line)
elif patch_kind == "repl_text":
idx = line.find(patch_data[0])
if idx > -1:
line = line.rstrip().replace(patch_data[0], patch_data[1])
line = "%s %s\n" % (line, patched_cmt)
else:
raise Exception("Unknown patch kind: %s" % patch_kind)
entered_function = False
lines.append(line)
tmp_file = "%s.tmp" % args.file
with open(tmp_file, "w") as f:
f.writelines(lines)
os.unlink(args.file)
os.rename(tmp_file, args.file)