diff options
| author | Axel Souchet <0vercl0k@tuxfamily.org> | 2018-09-09 06:11:00 -0700 |
|---|---|---|
| committer | serpilliere <serpilliere@users.noreply.github.com> | 2018-09-09 15:11:00 +0200 |
| commit | 8e6b39d80e9f8db8389bd2a8106d0f64b91c19e9 (patch) | |
| tree | dbf342089690704e89c10532b83d1d81709a49f4 /miasm2/jitter/jitcore_gcc.py | |
| parent | e61116884ac7879db08313542c6c28a8b00297c5 (diff) | |
| download | miasm-8e6b39d80e9f8db8389bd2a8106d0f64b91c19e9.tar.gz miasm-8e6b39d80e9f8db8389bd2a8106d0f64b91c19e9.zip | |
Adds Windows support and AppVeyor CI (#835)
* Get miasm to work on Windows, also add AppVeyor CI * Fix gcc jitter on Linux * Make the dse_crackme tests work on Windows * calling build and then install is less confusing than install twice * fix os.rename race condition on Windows * clean it up * Clean up after the unused cl.exe's artifacts * Use is_win instead of an additional check * Fix issue on Windows where 'w' and 'wb' modes are different * Address review feedback * setuptools is actually not required, so reverting
Diffstat (limited to 'miasm2/jitter/jitcore_gcc.py')
| -rw-r--r-- | miasm2/jitter/jitcore_gcc.py | 59 |
1 files changed, 50 insertions, 9 deletions
diff --git a/miasm2/jitter/jitcore_gcc.py b/miasm2/jitter/jitcore_gcc.py index dbaa2a08..238f2239 100644 --- a/miasm2/jitter/jitcore_gcc.py +++ b/miasm2/jitter/jitcore_gcc.py @@ -4,11 +4,14 @@ import os import tempfile import ctypes import _ctypes +import platform from subprocess import check_call +from distutils.sysconfig import get_python_inc from miasm2.jitter import Jitgcc from miasm2.jitter.jitcore_cc_base import JitCore_Cc_Base, gen_core +is_win = platform.system() == "Windows" class JitCore_Gcc(JitCore_Cc_Base): "JiT management, using a C compiler as backend" @@ -21,7 +24,12 @@ class JitCore_Gcc(JitCore_Cc_Base): """Free the state associated to @offset and delete it @offset: gcc state offset """ - _ctypes.dlclose(self.states[offset]._handle) + flib = None + if is_win: + flib = _ctypes.FreeLibrary + else: + flib = _ctypes.dlclose + flib(self.states[offset]._handle) del self.states[offset] def load_code(self, label, fname_so): @@ -37,7 +45,8 @@ class JitCore_Gcc(JitCore_Cc_Base): @block: block to jit """ block_hash = self.hash_block(block) - fname_out = os.path.join(self.tempdir, "%s.so" % block_hash) + ext = ".so" if not is_win else ".pyd" + fname_out = os.path.join(self.tempdir, "%s%s" % (block_hash, ext)) if not os.access(fname_out, os.R_OK | os.X_OK): func_code = self.gen_c_code(block) @@ -48,16 +57,49 @@ class JitCore_Gcc(JitCore_Cc_Base): os.close(fdesc) # Create unique SO file - fdesc, fname_tmp = tempfile.mkstemp(suffix=".so") + fdesc, fname_tmp = tempfile.mkstemp(suffix=ext) os.close(fdesc) inc_dir = ["-I%s" % inc for inc in self.include_files] libs = ["%s" % lib for lib in self.libs] - args = ["cc"] + ["-O3"] + [ - "-shared", "-fPIC", fname_in, '-o', fname_tmp] + inc_dir + libs - check_call(args) + if is_win: + libs.append(os.path.join(get_python_inc(), "..", "libs", "python27.lib")) + cl = [ + "cl", "/nologo", "/W3", "/MP", + "/Od", "/DNDEBUG", "/D_WINDOWS", "/Gm-", "/EHsc", + "/RTC1", "/MD", "/GS", + fname_in + ] + inc_dir + libs + cl += ["/link", "/DLL", "/OUT:" + fname_tmp] + out_dir, _ = os.path.split(fname_tmp) + check_call(cl, cwd = out_dir) + basename_out, _ = os.path.splitext(fname_tmp) + basename_in, _ = os.path.splitext(os.path.basename(fname_in)) + for ext in ('.obj', '.exp', '.lib'): + artifact_out_path = os.path.join(out_dir, basename_out + ext) + if os.path.isfile(artifact_out_path): + os.remove(artifact_out_path) + artifact_in_path = os.path.join(out_dir, basename_in + ext) + if os.path.isfile(artifact_in_path): + os.remove(artifact_in_path) + else: + args = ["cc", "-O3", "-shared", "-fPIC", fname_in, "-o", fname_tmp] + inc_dir + libs + check_call(args) + # Move temporary file to final file - os.rename(fname_tmp, fname_out) + try: + os.rename(fname_tmp, fname_out) + except WindowsError, e: + # On Windows, os.rename works slightly differently than on Linux; quoting the documentation: + # "On Unix, if dst exists and is a file, it will be replaced silently if the user has permission. + # The operation may fail on some Unix flavors if src and dst are on different filesystems. + # If successful, the renaming will be an atomic operation (this is a POSIX requirement). + # On Windows, if dst already exists, OSError will be raised even if it is a file; there may be no way + # to implement an atomic rename when dst names an existing file." + # [Error 183] Cannot create a file when that file already exists + if e.winerror != 183: + raise + os.remove(fname_tmp) os.remove(fname_in) self.load_code(block.loc_key, fname_out) @@ -68,6 +110,5 @@ class JitCore_Gcc(JitCore_Cc_Base): c_source += "\n".join(func_code) c_source = gen_core(ir_arch.arch, ir_arch.attrib) + c_source - c_source = "#include <Python.h>\n" + c_source - + c_source = "#define PARITY_IMPORT\n#include <Python.h>\n" + c_source return c_source |