├── README.txt ├── .gitattributes ├── proj.win32 ├── lua51.dll ├── lua │ └── jit │ │ ├── dis_x64.lua │ │ ├── dis_mipsel.lua │ │ ├── v.lua │ │ ├── bc.lua │ │ ├── vmdef.lua │ │ ├── dis_mips.lua │ │ ├── bcsave.lua │ │ ├── dis_arm.lua │ │ ├── dump.lua │ │ ├── dis_ppc.lua │ │ └── dis_x86.lua ├── EasyLuaEncryptor.vcxproj.filters ├── EasyLuaEncryptor.sln └── EasyLuaEncryptor.vcxproj ├── LICENSE ├── Classes ├── xxtea │ ├── xxtea.h │ └── xxtea.cpp └── EasyLuaEncryptor.cpp ├── .gitignore └── proj.mac └── EasyLuaEncryptor.xcodeproj └── project.pbxproj /README.txt: -------------------------------------------------------------------------------- 1 | 一键将目录下的所有lua脚本编译为luajit字节码(可选)并加密。 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Disable LF normalization for all files 2 | * -text -------------------------------------------------------------------------------- /proj.win32/lua51.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/qwer34/EasyLuaEncryptor/HEAD/proj.win32/lua51.dll -------------------------------------------------------------------------------- /proj.win32/lua/jit/dis_x64.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT x64 disassembler wrapper module. 3 | -- 4 | -- Copyright (C) 2005-2013 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- This module just exports the 64 bit functions from the combined 8 | -- x86/x64 disassembler module. All the interesting stuff is there. 9 | ------------------------------------------------------------------------------ 10 | 11 | local require = require 12 | 13 | module(...) 14 | 15 | local dis_x86 = require(_PACKAGE.."dis_x86") 16 | 17 | create = dis_x86.create64 18 | disass = dis_x86.disass64 19 | regname = dis_x86.regname64 20 | 21 | -------------------------------------------------------------------------------- /proj.win32/lua/jit/dis_mipsel.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT MIPSEL disassembler wrapper module. 3 | -- 4 | -- Copyright (C) 2005-2013 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- This module just exports the little-endian functions from the 8 | -- MIPS disassembler module. All the interesting stuff is there. 9 | ------------------------------------------------------------------------------ 10 | 11 | local require = require 12 | 13 | module(...) 14 | 15 | local dis_mips = require(_PACKAGE.."dis_mips") 16 | 17 | create = dis_mips.create_el 18 | disass = dis_mips.disass_el 19 | regname = dis_mips.regname 20 | 21 | -------------------------------------------------------------------------------- /proj.win32/EasyLuaEncryptor.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {e6fdfd8c-e2fd-442d-94b7-c8d25629da1e} 6 | 7 | 8 | {22154a52-6e82-4c6e-a051-291649520a44} 9 | 10 | 11 | 12 | 13 | Classes 14 | 15 | 16 | Classes\xxtea 17 | 18 | 19 | 20 | 21 | Classes\xxtea 22 | 23 | 24 | -------------------------------------------------------------------------------- /proj.win32/EasyLuaEncryptor.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.40629.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EasyLuaEncryptor", "EasyLuaEncryptor.vcxproj", "{B1F8B61C-E025-48DC-B4E1-A6873B999E23}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Release|Win32 = Release|Win32 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {B1F8B61C-E025-48DC-B4E1-A6873B999E23}.Debug|Win32.ActiveCfg = Debug|Win32 15 | {B1F8B61C-E025-48DC-B4E1-A6873B999E23}.Debug|Win32.Build.0 = Debug|Win32 16 | {B1F8B61C-E025-48DC-B4E1-A6873B999E23}.Release|Win32.ActiveCfg = Release|Win32 17 | {B1F8B61C-E025-48DC-B4E1-A6873B999E23}.Release|Win32.Build.0 = Release|Win32 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Xin Zhang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Classes/xxtea/xxtea.h: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | 3 | Copyright 2006-2009 Ma Bingyao 4 | Copyright 2013 Gao Chunhui, Liu Tao 5 | 6 | These sources is free software. Redistributions of source code must 7 | retain the above copyright notice. Redistributions in binary form 8 | must reproduce the above copyright notice. You can redistribute it 9 | freely. You can use it with any free or commercial software. 10 | 11 | These sources is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY. Without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 | 15 | github: https://github.com/liut/pecl-xxtea 16 | 17 | *************************************************************************/ 18 | 19 | #ifndef XXTEA_H 20 | #define XXTEA_H 21 | 22 | #include /* for size_t & NULL declarations */ 23 | 24 | #if defined(_MSC_VER) 25 | 26 | typedef unsigned __int32 xxtea_long; 27 | 28 | #else 29 | 30 | #if defined(__FreeBSD__) && __FreeBSD__ < 5 31 | /* FreeBSD 4 doesn't have stdint.h file */ 32 | #include 33 | #else 34 | #include 35 | #endif 36 | 37 | typedef uint32_t xxtea_long; 38 | 39 | #endif /* end of if defined(_MSC_VER) */ 40 | 41 | #define XXTEA_MX (z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z) 42 | #define XXTEA_DELTA 0x9e3779b9 43 | 44 | unsigned char *xxtea_encrypt(unsigned char *data, xxtea_long data_len, unsigned char *key, xxtea_long key_len, xxtea_long *ret_length); 45 | unsigned char *xxtea_decrypt(unsigned char *data, xxtea_long data_len, unsigned char *key, xxtea_long key_len, xxtea_long *ret_length); 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore thumbnails created by windows 2 | Thumbs.db 3 | 4 | # Ignore files build by Visual Studio 5 | *.obj 6 | *.exe 7 | *.pdb 8 | *.aps 9 | *.vcproj.*.user 10 | *.vcxproj.user 11 | *.csproj.user 12 | *.vspscc 13 | *_i.c 14 | *.i 15 | *.icf 16 | *_p.c 17 | *.ncb 18 | *.suo 19 | *.tlb 20 | *.tlh 21 | *.bak 22 | *.cache 23 | *.ilk 24 | *.log 25 | [Bb]in 26 | [Dd]ebug/ 27 | [Dd]ebug.win32/ 28 | *.sbr 29 | *.sdf 30 | obj/ 31 | [Rr]elease/ 32 | [Rr]elease.win32/ 33 | _ReSharper*/ 34 | [Tt]est[Rr]esult* 35 | ipch/ 36 | *.opensdf 37 | SubmissionInfo 38 | Generated Files 39 | AppPackages 40 | .vs/ 41 | 42 | # Ignore files build by ndk and eclipse 43 | libs/ 44 | bin/ 45 | obj/ 46 | gen/ 47 | assets/ 48 | local.properties 49 | 50 | # Ignore python compiled files 51 | *.pyc 52 | 53 | # Ignore files build by airplay and marmalade 54 | build_*_xcode/ 55 | build_*_vc10/ 56 | 57 | # Ignore files build by xcode 58 | *.mode*v* 59 | *.pbxuser 60 | *.xcbkptlist 61 | *.xcworkspacedata 62 | *.xcuserstate 63 | *.xccheckout 64 | xcschememanagement.plist 65 | .DS_Store 66 | ._.* 67 | xcuserdata/ 68 | DerivedData/ 69 | 70 | # Ignore files built by AppCode 71 | .idea/ 72 | 73 | # Ignore files built by bada 74 | .Simulator-Debug/ 75 | .Target-Debug/ 76 | .Target-Release/ 77 | 78 | # Ignore files built by blackberry 79 | Simulator/ 80 | Device-Debug/ 81 | Device-Release/ 82 | 83 | # Ignore vim swaps 84 | *.swp 85 | *.swo 86 | 87 | # Ignore files created by create_project.py 88 | projects/ 89 | 90 | # Ignore config files in javascript bindings generator 91 | tools/tojs/user.cfg 92 | # ... userconf.ini generated if running from tools/tojs 93 | tools/tojs/userconf.ini 94 | tools/tolua/userconf.ini 95 | # ... userconf.ini generated if running from tools/jenkins_scripts/mac/android/ 96 | tools/jenkins_scripts/mac/android/userconf.ini 97 | 98 | # CTags 99 | tags 100 | 101 | # ignore files, created with make-all-linux-project script 102 | /lib 103 | /build/linux-build 104 | 105 | # Cmake files 106 | CMakeCache.txt 107 | CMakeFiles 108 | Makefile 109 | cmake_install.cmake 110 | CMakeLists.txt.user 111 | 112 | # Ignore files generated by console 113 | build/build/ 114 | cocos/scripting/lua-bindings/proj.ios_mac/build/ 115 | tests/*/runtime/ 116 | tests/*/publish/ 117 | tests/*/project/proj.android-studio/app/build.xml 118 | tests/*/project/proj.android-studio/app/proguard-project.txt 119 | tests/*/proj.android-studio/app/build.xml 120 | tests/*/proj.android-studio/app/proguard-project.txt 121 | 122 | # Android 123 | project.properties 124 | *.iml 125 | 126 | # Ignore prebuilt libraries folder 127 | /external/* 128 | !/external/config.json 129 | /templates/lua-template-runtime/runtime 130 | /v*-deps-*.zip 131 | /v*-lua-runtime-*.zip 132 | /v*-console-*.zip 133 | /tools/fbx-conv/ 134 | tests/cpp-tests/Resources/audio 135 | /tests/lua-empty-test/src/cocos/ 136 | /tests/lua-game-controller-test/src/cocos/ 137 | /tests/lua-tests/src/cocos/ 138 | /tests/js-tests/res/ 139 | /tools/framework-compile/bin/proj_modifier/plutil-win32/ 140 | !/tools/framework-compile/bin/ 141 | 142 | # generated by framework-compile 143 | /templates/*-template-binary/ 144 | /prebuilt/ 145 | /*/prebuilt-mk/Android.mk 146 | /*/*/prebuilt-mk/Android.mk 147 | /*/*/*/prebuilt-mk/Android.mk 148 | /*/*/*/*/prebuilt-mk/Android.mk 149 | 150 | *.TMP 151 | *.db -------------------------------------------------------------------------------- /Classes/xxtea/xxtea.cpp: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | 3 | Copyright 2006-2009 Ma Bingyao 4 | Copyright 2013 Gao Chunhui, Liu Tao 5 | 6 | These sources is free software. Redistributions of source code must 7 | retain the above copyright notice. Redistributions in binary form 8 | must reproduce the above copyright notice. You can redistribute it 9 | freely. You can use it with any free or commercial software. 10 | 11 | These sources is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY. Without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 | 15 | github: https://github.com/liut/pecl-xxtea 16 | 17 | *************************************************************************/ 18 | 19 | #include "xxtea.h" 20 | #include 21 | #include 22 | 23 | static void xxtea_long_encrypt(xxtea_long *v, xxtea_long len, xxtea_long *k) 24 | { 25 | xxtea_long n = len - 1; 26 | xxtea_long z = v[n], y = v[0], p, q = 6 + 52 / (n + 1), sum = 0, e; 27 | if (n < 1) { 28 | return; 29 | } 30 | while (0 < q--) { 31 | sum += XXTEA_DELTA; 32 | e = sum >> 2 & 3; 33 | for (p = 0; p < n; p++) { 34 | y = v[p + 1]; 35 | z = v[p] += XXTEA_MX; 36 | } 37 | y = v[0]; 38 | z = v[n] += XXTEA_MX; 39 | } 40 | } 41 | 42 | static void xxtea_long_decrypt(xxtea_long *v, xxtea_long len, xxtea_long *k) 43 | { 44 | xxtea_long n = len - 1; 45 | xxtea_long z = v[n], y = v[0], p, q = 6 + 52 / (n + 1), sum = q * XXTEA_DELTA, e; 46 | if (n < 1) { 47 | return; 48 | } 49 | while (sum != 0) { 50 | e = sum >> 2 & 3; 51 | for (p = n; p > 0; p--) { 52 | z = v[p - 1]; 53 | y = v[p] -= XXTEA_MX; 54 | } 55 | z = v[n]; 56 | y = v[0] -= XXTEA_MX; 57 | sum -= XXTEA_DELTA; 58 | } 59 | } 60 | 61 | static unsigned char *fix_key_length(unsigned char *key, xxtea_long key_len) 62 | { 63 | unsigned char *tmp = (unsigned char *)malloc(16); 64 | memcpy(tmp, key, key_len); 65 | memset(tmp + key_len, '\0', 16 - key_len); 66 | return tmp; 67 | } 68 | 69 | static xxtea_long *xxtea_to_long_array(unsigned char *data, xxtea_long len, int include_length, xxtea_long *ret_len) { 70 | xxtea_long i, n, *result; 71 | 72 | n = len >> 2; 73 | n = (((len & 3) == 0) ? n : n + 1); 74 | if (include_length) { 75 | result = (xxtea_long *)malloc((n + 1) << 2); 76 | result[n] = len; 77 | *ret_len = n + 1; 78 | } else { 79 | result = (xxtea_long *)malloc(n << 2); 80 | *ret_len = n; 81 | } 82 | memset(result, 0, n << 2); 83 | for (i = 0; i < len; i++) { 84 | result[i >> 2] |= (xxtea_long)data[i] << ((i & 3) << 3); 85 | } 86 | 87 | return result; 88 | } 89 | 90 | static unsigned char *xxtea_to_byte_array(xxtea_long *data, xxtea_long len, int include_length, xxtea_long *ret_len) { 91 | xxtea_long i, n, m; 92 | unsigned char *result; 93 | 94 | n = len << 2; 95 | if (include_length) { 96 | m = data[len - 1]; 97 | if ((m < n - 7) || (m > n - 4)) return NULL; 98 | n = m; 99 | } 100 | result = (unsigned char *)malloc(n + 1); 101 | for (i = 0; i < n; i++) { 102 | result[i] = (unsigned char)((data[i >> 2] >> ((i & 3) << 3)) & 0xff); 103 | } 104 | result[n] = '\0'; 105 | *ret_len = n; 106 | 107 | return result; 108 | } 109 | 110 | static unsigned char *do_xxtea_encrypt(unsigned char *data, xxtea_long len, unsigned char *key, xxtea_long *ret_len) { 111 | unsigned char *result; 112 | xxtea_long *v, *k, v_len, k_len; 113 | 114 | v = xxtea_to_long_array(data, len, 1, &v_len); 115 | k = xxtea_to_long_array(key, 16, 0, &k_len); 116 | xxtea_long_encrypt(v, v_len, k); 117 | result = xxtea_to_byte_array(v, v_len, 0, ret_len); 118 | free(v); 119 | free(k); 120 | 121 | return result; 122 | } 123 | 124 | static unsigned char *do_xxtea_decrypt(unsigned char *data, xxtea_long len, unsigned char *key, xxtea_long *ret_len) { 125 | unsigned char *result; 126 | xxtea_long *v, *k, v_len, k_len; 127 | 128 | v = xxtea_to_long_array(data, len, 0, &v_len); 129 | k = xxtea_to_long_array(key, 16, 0, &k_len); 130 | xxtea_long_decrypt(v, v_len, k); 131 | result = xxtea_to_byte_array(v, v_len, 1, ret_len); 132 | free(v); 133 | free(k); 134 | 135 | return result; 136 | } 137 | 138 | unsigned char *xxtea_encrypt(unsigned char *data, xxtea_long data_len, unsigned char *key, xxtea_long key_len, xxtea_long *ret_length) 139 | { 140 | unsigned char *result; 141 | 142 | *ret_length = 0; 143 | 144 | if (key_len < 16) { 145 | unsigned char *key2 = fix_key_length(key, key_len); 146 | result = do_xxtea_encrypt(data, data_len, key2, ret_length); 147 | free(key2); 148 | } 149 | else 150 | { 151 | result = do_xxtea_encrypt(data, data_len, key, ret_length); 152 | } 153 | 154 | return result; 155 | } 156 | 157 | unsigned char *xxtea_decrypt(unsigned char *data, xxtea_long data_len, unsigned char *key, xxtea_long key_len, xxtea_long *ret_length) 158 | { 159 | unsigned char *result; 160 | 161 | *ret_length = 0; 162 | 163 | if (key_len < 16) { 164 | unsigned char *key2 = fix_key_length(key, key_len); 165 | result = do_xxtea_decrypt(data, data_len, key2, ret_length); 166 | free(key2); 167 | } 168 | else 169 | { 170 | result = do_xxtea_decrypt(data, data_len, key, ret_length); 171 | } 172 | 173 | return result; 174 | } 175 | 176 | /* }}} */ 177 | -------------------------------------------------------------------------------- /proj.win32/EasyLuaEncryptor.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {B1F8B61C-E025-48DC-B4E1-A6873B999E23} 22 | Win32Proj 23 | EasyLuaEncryptor 24 | 25 | 26 | 27 | Application 28 | true 29 | v120_xp 30 | MultiByte 31 | 32 | 33 | Application 34 | false 35 | v120_xp 36 | true 37 | MultiByte 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | true 51 | 52 | 53 | false 54 | 55 | 56 | 57 | 58 | 59 | Level3 60 | Disabled 61 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 62 | true 63 | AdvancedVectorExtensions2 64 | Fast 65 | true 66 | MultiThreadedDebug 67 | 68 | 69 | Console 70 | true 71 | 72 | 73 | copy /B /Y $(ProjectDir)luajit.exe $(OutDir) 74 | copy /B /Y $(ProjectDir)lua51.dll $(OutDir) 75 | mkdir $(OutDir)lua 76 | xcopy $(ProjectDir)lua\* $(OutDir)lua /S /R /Y 77 | 78 | 79 | 80 | 81 | Level3 82 | 83 | 84 | Full 85 | true 86 | true 87 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 88 | true 89 | AdvancedVectorExtensions2 90 | Fast 91 | Speed 92 | true 93 | None 94 | MultiThreaded 95 | 96 | 97 | Console 98 | false 99 | true 100 | true 101 | 102 | 103 | copy /B /Y $(ProjectDir)luajit.exe $(OutDir) 104 | copy /B /Y $(ProjectDir)lua51.dll $(OutDir) 105 | mkdir $(OutDir)lua 106 | xcopy $(ProjectDir)lua\* $(OutDir)lua /S /R /Y 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /proj.win32/lua/jit/v.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- Verbose mode of the LuaJIT compiler. 3 | -- 4 | -- Copyright (C) 2005-2013 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- 8 | -- This module shows verbose information about the progress of the 9 | -- JIT compiler. It prints one line for each generated trace. This module 10 | -- is useful to see which code has been compiled or where the compiler 11 | -- punts and falls back to the interpreter. 12 | -- 13 | -- Example usage: 14 | -- 15 | -- luajit -jv -e "for i=1,1000 do for j=1,1000 do end end" 16 | -- luajit -jv=myapp.out myapp.lua 17 | -- 18 | -- Default output is to stderr. To redirect the output to a file, pass a 19 | -- filename as an argument (use '-' for stdout) or set the environment 20 | -- variable LUAJIT_VERBOSEFILE. The file is overwritten every time the 21 | -- module is started. 22 | -- 23 | -- The output from the first example should look like this: 24 | -- 25 | -- [TRACE 1 (command line):1 loop] 26 | -- [TRACE 2 (1/3) (command line):1 -> 1] 27 | -- 28 | -- The first number in each line is the internal trace number. Next are 29 | -- the file name ('(command line)') and the line number (':1') where the 30 | -- trace has started. Side traces also show the parent trace number and 31 | -- the exit number where they are attached to in parentheses ('(1/3)'). 32 | -- An arrow at the end shows where the trace links to ('-> 1'), unless 33 | -- it loops to itself. 34 | -- 35 | -- In this case the inner loop gets hot and is traced first, generating 36 | -- a root trace. Then the last exit from the 1st trace gets hot, too, 37 | -- and triggers generation of the 2nd trace. The side trace follows the 38 | -- path along the outer loop and *around* the inner loop, back to its 39 | -- start, and then links to the 1st trace. Yes, this may seem unusual, 40 | -- if you know how traditional compilers work. Trace compilers are full 41 | -- of surprises like this -- have fun! :-) 42 | -- 43 | -- Aborted traces are shown like this: 44 | -- 45 | -- [TRACE --- foo.lua:44 -- leaving loop in root trace at foo:lua:50] 46 | -- 47 | -- Don't worry -- trace aborts are quite common, even in programs which 48 | -- can be fully compiled. The compiler may retry several times until it 49 | -- finds a suitable trace. 50 | -- 51 | -- Of course this doesn't work with features that are not-yet-implemented 52 | -- (NYI error messages). The VM simply falls back to the interpreter. This 53 | -- may not matter at all if the particular trace is not very high up in 54 | -- the CPU usage profile. Oh, and the interpreter is quite fast, too. 55 | -- 56 | -- Also check out the -jdump module, which prints all the gory details. 57 | -- 58 | ------------------------------------------------------------------------------ 59 | 60 | -- Cache some library functions and objects. 61 | local jit = require("jit") 62 | assert(jit.version_num == 20001, "LuaJIT core/library version mismatch") 63 | local jutil = require("jit.util") 64 | local vmdef = require("jit.vmdef") 65 | local funcinfo, traceinfo = jutil.funcinfo, jutil.traceinfo 66 | local type, format = type, string.format 67 | local stdout, stderr = io.stdout, io.stderr 68 | 69 | -- Active flag and output file handle. 70 | local active, out 71 | 72 | ------------------------------------------------------------------------------ 73 | 74 | local startloc, startex 75 | 76 | local function fmtfunc(func, pc) 77 | local fi = funcinfo(func, pc) 78 | if fi.loc then 79 | return fi.loc 80 | elseif fi.ffid then 81 | return vmdef.ffnames[fi.ffid] 82 | elseif fi.addr then 83 | return format("C:%x", fi.addr) 84 | else 85 | return "(?)" 86 | end 87 | end 88 | 89 | -- Format trace error message. 90 | local function fmterr(err, info) 91 | if type(err) == "number" then 92 | if type(info) == "function" then info = fmtfunc(info) end 93 | err = format(vmdef.traceerr[err], info) 94 | end 95 | return err 96 | end 97 | 98 | -- Dump trace states. 99 | local function dump_trace(what, tr, func, pc, otr, oex) 100 | if what == "start" then 101 | startloc = fmtfunc(func, pc) 102 | startex = otr and "("..otr.."/"..oex..") " or "" 103 | else 104 | if what == "abort" then 105 | local loc = fmtfunc(func, pc) 106 | if loc ~= startloc then 107 | out:write(format("[TRACE --- %s%s -- %s at %s]\n", 108 | startex, startloc, fmterr(otr, oex), loc)) 109 | else 110 | out:write(format("[TRACE --- %s%s -- %s]\n", 111 | startex, startloc, fmterr(otr, oex))) 112 | end 113 | elseif what == "stop" then 114 | local info = traceinfo(tr) 115 | local link, ltype = info.link, info.linktype 116 | if ltype == "interpreter" then 117 | out:write(format("[TRACE %3s %s%s -- fallback to interpreter]\n", 118 | tr, startex, startloc)) 119 | elseif link == tr or link == 0 then 120 | out:write(format("[TRACE %3s %s%s %s]\n", 121 | tr, startex, startloc, ltype)) 122 | elseif ltype == "root" then 123 | out:write(format("[TRACE %3s %s%s -> %d]\n", 124 | tr, startex, startloc, link)) 125 | else 126 | out:write(format("[TRACE %3s %s%s -> %d %s]\n", 127 | tr, startex, startloc, link, ltype)) 128 | end 129 | else 130 | out:write(format("[TRACE %s]\n", what)) 131 | end 132 | out:flush() 133 | end 134 | end 135 | 136 | ------------------------------------------------------------------------------ 137 | 138 | -- Detach dump handlers. 139 | local function dumpoff() 140 | if active then 141 | active = false 142 | jit.attach(dump_trace) 143 | if out and out ~= stdout and out ~= stderr then out:close() end 144 | out = nil 145 | end 146 | end 147 | 148 | -- Open the output file and attach dump handlers. 149 | local function dumpon(outfile) 150 | if active then dumpoff() end 151 | if not outfile then outfile = os.getenv("LUAJIT_VERBOSEFILE") end 152 | if outfile then 153 | out = outfile == "-" and stdout or assert(io.open(outfile, "w")) 154 | else 155 | out = stderr 156 | end 157 | jit.attach(dump_trace, "trace") 158 | active = true 159 | end 160 | 161 | -- Public module functions. 162 | module(...) 163 | 164 | on = dumpon 165 | off = dumpoff 166 | start = dumpon -- For -j command line option. 167 | 168 | -------------------------------------------------------------------------------- /proj.win32/lua/jit/bc.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT bytecode listing module. 3 | -- 4 | -- Copyright (C) 2005-2013 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- 8 | -- This module lists the bytecode of a Lua function. If it's loaded by -jbc 9 | -- it hooks into the parser and lists all functions of a chunk as they 10 | -- are parsed. 11 | -- 12 | -- Example usage: 13 | -- 14 | -- luajit -jbc -e 'local x=0; for i=1,1e6 do x=x+i end; print(x)' 15 | -- luajit -jbc=- foo.lua 16 | -- luajit -jbc=foo.list foo.lua 17 | -- 18 | -- Default output is to stderr. To redirect the output to a file, pass a 19 | -- filename as an argument (use '-' for stdout) or set the environment 20 | -- variable LUAJIT_LISTFILE. The file is overwritten every time the module 21 | -- is started. 22 | -- 23 | -- This module can also be used programmatically: 24 | -- 25 | -- local bc = require("jit.bc") 26 | -- 27 | -- local function foo() print("hello") end 28 | -- 29 | -- bc.dump(foo) --> -- BYTECODE -- [...] 30 | -- print(bc.line(foo, 2)) --> 0002 KSTR 1 1 ; "hello" 31 | -- 32 | -- local out = { 33 | -- -- Do something with each line: 34 | -- write = function(t, ...) io.write(...) end, 35 | -- close = function(t) end, 36 | -- flush = function(t) end, 37 | -- } 38 | -- bc.dump(foo, out) 39 | -- 40 | ------------------------------------------------------------------------------ 41 | 42 | -- Cache some library functions and objects. 43 | local jit = require("jit") 44 | assert(jit.version_num == 20001, "LuaJIT core/library version mismatch") 45 | local jutil = require("jit.util") 46 | local vmdef = require("jit.vmdef") 47 | local bit = require("bit") 48 | local sub, gsub, format = string.sub, string.gsub, string.format 49 | local byte, band, shr = string.byte, bit.band, bit.rshift 50 | local funcinfo, funcbc, funck = jutil.funcinfo, jutil.funcbc, jutil.funck 51 | local funcuvname = jutil.funcuvname 52 | local bcnames = vmdef.bcnames 53 | local stdout, stderr = io.stdout, io.stderr 54 | 55 | ------------------------------------------------------------------------------ 56 | 57 | local function ctlsub(c) 58 | if c == "\n" then return "\\n" 59 | elseif c == "\r" then return "\\r" 60 | elseif c == "\t" then return "\\t" 61 | else return format("\\%03d", byte(c)) 62 | end 63 | end 64 | 65 | -- Return one bytecode line. 66 | local function bcline(func, pc, prefix) 67 | local ins, m = funcbc(func, pc) 68 | if not ins then return end 69 | local ma, mb, mc = band(m, 7), band(m, 15*8), band(m, 15*128) 70 | local a = band(shr(ins, 8), 0xff) 71 | local oidx = 6*band(ins, 0xff) 72 | local op = sub(bcnames, oidx+1, oidx+6) 73 | local s = format("%04d %s %-6s %3s ", 74 | pc, prefix or " ", op, ma == 0 and "" or a) 75 | local d = shr(ins, 16) 76 | if mc == 13*128 then -- BCMjump 77 | return format("%s=> %04d\n", s, pc+d-0x7fff) 78 | end 79 | if mb ~= 0 then 80 | d = band(d, 0xff) 81 | elseif mc == 0 then 82 | return s.."\n" 83 | end 84 | local kc 85 | if mc == 10*128 then -- BCMstr 86 | kc = funck(func, -d-1) 87 | kc = format(#kc > 40 and '"%.40s"~' or '"%s"', gsub(kc, "%c", ctlsub)) 88 | elseif mc == 9*128 then -- BCMnum 89 | kc = funck(func, d) 90 | if op == "TSETM " then kc = kc - 2^52 end 91 | elseif mc == 12*128 then -- BCMfunc 92 | local fi = funcinfo(funck(func, -d-1)) 93 | if fi.ffid then 94 | kc = vmdef.ffnames[fi.ffid] 95 | else 96 | kc = fi.loc 97 | end 98 | elseif mc == 5*128 then -- BCMuv 99 | kc = funcuvname(func, d) 100 | end 101 | if ma == 5 then -- BCMuv 102 | local ka = funcuvname(func, a) 103 | if kc then kc = ka.." ; "..kc else kc = ka end 104 | end 105 | if mb ~= 0 then 106 | local b = shr(ins, 24) 107 | if kc then return format("%s%3d %3d ; %s\n", s, b, d, kc) end 108 | return format("%s%3d %3d\n", s, b, d) 109 | end 110 | if kc then return format("%s%3d ; %s\n", s, d, kc) end 111 | if mc == 7*128 and d > 32767 then d = d - 65536 end -- BCMlits 112 | return format("%s%3d\n", s, d) 113 | end 114 | 115 | -- Collect branch targets of a function. 116 | local function bctargets(func) 117 | local target = {} 118 | for pc=1,1000000000 do 119 | local ins, m = funcbc(func, pc) 120 | if not ins then break end 121 | if band(m, 15*128) == 13*128 then target[pc+shr(ins, 16)-0x7fff] = true end 122 | end 123 | return target 124 | end 125 | 126 | -- Dump bytecode instructions of a function. 127 | local function bcdump(func, out, all) 128 | if not out then out = stdout end 129 | local fi = funcinfo(func) 130 | if all and fi.children then 131 | for n=-1,-1000000000,-1 do 132 | local k = funck(func, n) 133 | if not k then break end 134 | if type(k) == "proto" then bcdump(k, out, true) end 135 | end 136 | end 137 | out:write(format("-- BYTECODE -- %s-%d\n", fi.loc, fi.lastlinedefined)) 138 | local target = bctargets(func) 139 | for pc=1,1000000000 do 140 | local s = bcline(func, pc, target[pc] and "=>") 141 | if not s then break end 142 | out:write(s) 143 | end 144 | out:write("\n") 145 | out:flush() 146 | end 147 | 148 | ------------------------------------------------------------------------------ 149 | 150 | -- Active flag and output file handle. 151 | local active, out 152 | 153 | -- List handler. 154 | local function h_list(func) 155 | return bcdump(func, out) 156 | end 157 | 158 | -- Detach list handler. 159 | local function bclistoff() 160 | if active then 161 | active = false 162 | jit.attach(h_list) 163 | if out and out ~= stdout and out ~= stderr then out:close() end 164 | out = nil 165 | end 166 | end 167 | 168 | -- Open the output file and attach list handler. 169 | local function bcliston(outfile) 170 | if active then bclistoff() end 171 | if not outfile then outfile = os.getenv("LUAJIT_LISTFILE") end 172 | if outfile then 173 | out = outfile == "-" and stdout or assert(io.open(outfile, "w")) 174 | else 175 | out = stderr 176 | end 177 | jit.attach(h_list, "bc") 178 | active = true 179 | end 180 | 181 | -- Public module functions. 182 | module(...) 183 | 184 | line = bcline 185 | dump = bcdump 186 | targets = bctargets 187 | 188 | on = bcliston 189 | off = bclistoff 190 | start = bcliston -- For -j command line option. 191 | 192 | -------------------------------------------------------------------------------- /proj.win32/lua/jit/vmdef.lua: -------------------------------------------------------------------------------- 1 | -- This is a generated file. DO NOT EDIT! 2 | 3 | module(...) 4 | 5 | bcnames = "ISLT ISGE ISLE ISGT ISEQV ISNEV ISEQS ISNES ISEQN ISNEN ISEQP ISNEP ISTC ISFC IST ISF MOV NOT UNM LEN ADDVN SUBVN MULVN DIVVN MODVN ADDNV SUBNV MULNV DIVNV MODNV ADDVV SUBVV MULVV DIVVV MODVV POW CAT KSTR KCDATAKSHORTKNUM KPRI KNIL UGET USETV USETS USETN USETP UCLO FNEW TNEW TDUP GGET GSET TGETV TGETS TGETB TSETV TSETS TSETB TSETM CALLM CALL CALLMTCALLT ITERC ITERN VARG ISNEXTRETM RET RET0 RET1 FORI JFORI FORL IFORL JFORL ITERL IITERLJITERLLOOP ILOOP JLOOP JMP FUNCF IFUNCFJFUNCFFUNCV IFUNCVJFUNCVFUNCC FUNCCW" 6 | 7 | irnames = "LT GE LE GT ULT UGE ULE UGT EQ NE ABC RETF NOP BASE PVAL GCSTEPHIOP LOOP USE PHI RENAMEKPRI KINT KGC KPTR KKPTR KNULL KNUM KINT64KSLOT BNOT BSWAP BAND BOR BXOR BSHL BSHR BSAR BROL BROR ADD SUB MUL DIV MOD POW NEG ABS ATAN2 LDEXP MIN MAX FPMATHADDOV SUBOV MULOV AREF HREFK HREF NEWREFUREFO UREFC FREF STRREFALOAD HLOAD ULOAD FLOAD XLOAD SLOAD VLOAD ASTOREHSTOREUSTOREFSTOREXSTORESNEW XSNEW TNEW TDUP CNEW CNEWI TBAR OBAR XBAR CONV TOBIT TOSTR STRTO CALLN CALLL CALLS CALLXSCARG " 8 | 9 | irfpm = { [0]="floor", "ceil", "trunc", "sqrt", "exp", "exp2", "log", "log2", "log10", "sin", "cos", "tan", "other", } 10 | 11 | irfield = { [0]="str.len", "func.env", "func.pc", "tab.meta", "tab.array", "tab.node", "tab.asize", "tab.hmask", "tab.nomm", "udata.meta", "udata.udtype", "udata.file", "cdata.ctypeid", "cdata.ptr", "cdata.int", "cdata.int64", "cdata.int64_4", } 12 | 13 | ircall = { 14 | [0]="lj_str_cmp", 15 | "lj_str_new", 16 | "lj_strscan_num", 17 | "lj_str_fromint", 18 | "lj_str_fromnum", 19 | "lj_tab_new1", 20 | "lj_tab_dup", 21 | "lj_tab_newkey", 22 | "lj_tab_len", 23 | "lj_gc_step_jit", 24 | "lj_gc_barrieruv", 25 | "lj_mem_newgco", 26 | "lj_math_random_step", 27 | "lj_vm_modi", 28 | "sinh", 29 | "cosh", 30 | "tanh", 31 | "fputc", 32 | "fwrite", 33 | "fflush", 34 | "lj_vm_floor", 35 | "lj_vm_ceil", 36 | "lj_vm_trunc", 37 | "sqrt", 38 | "exp", 39 | "lj_vm_exp2", 40 | "log", 41 | "lj_vm_log2", 42 | "log10", 43 | "sin", 44 | "cos", 45 | "tan", 46 | "lj_vm_powi", 47 | "pow", 48 | "atan2", 49 | "ldexp", 50 | "lj_vm_tobit", 51 | "softfp_add", 52 | "softfp_sub", 53 | "softfp_mul", 54 | "softfp_div", 55 | "softfp_cmp", 56 | "softfp_i2d", 57 | "softfp_d2i", 58 | "softfp_ui2d", 59 | "softfp_f2d", 60 | "softfp_d2ui", 61 | "softfp_d2f", 62 | "softfp_i2f", 63 | "softfp_ui2f", 64 | "softfp_f2i", 65 | "softfp_f2ui", 66 | "fp64_l2d", 67 | "fp64_ul2d", 68 | "fp64_l2f", 69 | "fp64_ul2f", 70 | "fp64_d2l", 71 | "fp64_d2ul", 72 | "fp64_f2l", 73 | "fp64_f2ul", 74 | "lj_carith_divi64", 75 | "lj_carith_divu64", 76 | "lj_carith_modi64", 77 | "lj_carith_modu64", 78 | "lj_carith_powi64", 79 | "lj_carith_powu64", 80 | "lj_cdata_setfin", 81 | "strlen", 82 | "memcpy", 83 | "memset", 84 | "lj_vm_errno", 85 | "lj_carith_mul64", 86 | } 87 | 88 | traceerr = { 89 | [0]="error thrown or hook called during recording", 90 | "trace too long", 91 | "trace too deep", 92 | "too many snapshots", 93 | "blacklisted", 94 | "NYI: bytecode %d", 95 | "leaving loop in root trace", 96 | "inner loop in root trace", 97 | "loop unroll limit reached", 98 | "bad argument type", 99 | "call to JIT-disabled function", 100 | "call unroll limit reached", 101 | "down-recursion, restarting", 102 | "NYI: C function %p", 103 | "NYI: FastFunc %s", 104 | "NYI: unsupported variant of FastFunc %s", 105 | "NYI: return to lower frame", 106 | "store with nil or NaN key", 107 | "missing metamethod", 108 | "looping index lookup", 109 | "NYI: mixed sparse/dense table", 110 | "symbol not in cache", 111 | "NYI: unsupported C type conversion", 112 | "NYI: unsupported C function type", 113 | "guard would always fail", 114 | "too many PHIs", 115 | "persistent type instability", 116 | "failed to allocate mcode memory", 117 | "machine code too long", 118 | "hit mcode limit (retrying)", 119 | "too many spill slots", 120 | "inconsistent register allocation", 121 | "NYI: cannot assemble IR instruction %d", 122 | "NYI: PHI shuffling too complex", 123 | "NYI: register coalescing too complex", 124 | } 125 | 126 | ffnames = { 127 | [0]="Lua", 128 | "C", 129 | "assert", 130 | "type", 131 | "next", 132 | "pairs", 133 | "ipairs_aux", 134 | "ipairs", 135 | "getmetatable", 136 | "setmetatable", 137 | "getfenv", 138 | "setfenv", 139 | "rawget", 140 | "rawset", 141 | "rawequal", 142 | "unpack", 143 | "select", 144 | "tonumber", 145 | "tostring", 146 | "error", 147 | "pcall", 148 | "xpcall", 149 | "loadfile", 150 | "load", 151 | "loadstring", 152 | "dofile", 153 | "gcinfo", 154 | "collectgarbage", 155 | "newproxy", 156 | "print", 157 | "coroutine.status", 158 | "coroutine.running", 159 | "coroutine.create", 160 | "coroutine.yield", 161 | "coroutine.resume", 162 | "coroutine.wrap_aux", 163 | "coroutine.wrap", 164 | "math.abs", 165 | "math.floor", 166 | "math.ceil", 167 | "math.sqrt", 168 | "math.log10", 169 | "math.exp", 170 | "math.sin", 171 | "math.cos", 172 | "math.tan", 173 | "math.asin", 174 | "math.acos", 175 | "math.atan", 176 | "math.sinh", 177 | "math.cosh", 178 | "math.tanh", 179 | "math.frexp", 180 | "math.modf", 181 | "math.log", 182 | "math.deg", 183 | "math.rad", 184 | "math.atan2", 185 | "math.pow", 186 | "math.fmod", 187 | "math.ldexp", 188 | "math.min", 189 | "math.max", 190 | "math.random", 191 | "math.randomseed", 192 | "bit.tobit", 193 | "bit.bnot", 194 | "bit.bswap", 195 | "bit.lshift", 196 | "bit.rshift", 197 | "bit.arshift", 198 | "bit.rol", 199 | "bit.ror", 200 | "bit.band", 201 | "bit.bor", 202 | "bit.bxor", 203 | "bit.tohex", 204 | "string.len", 205 | "string.byte", 206 | "string.char", 207 | "string.sub", 208 | "string.rep", 209 | "string.reverse", 210 | "string.lower", 211 | "string.upper", 212 | "string.dump", 213 | "string.find", 214 | "string.match", 215 | "string.gmatch_aux", 216 | "string.gmatch", 217 | "string.gsub", 218 | "string.format", 219 | "table.foreachi", 220 | "table.foreach", 221 | "table.getn", 222 | "table.maxn", 223 | "table.insert", 224 | "table.remove", 225 | "table.concat", 226 | "table.sort", 227 | "io.method.close", 228 | "io.method.read", 229 | "io.method.write", 230 | "io.method.flush", 231 | "io.method.seek", 232 | "io.method.setvbuf", 233 | "io.method.lines", 234 | "io.method.__gc", 235 | "io.method.__tostring", 236 | "io.open", 237 | "io.popen", 238 | "io.tmpfile", 239 | "io.close", 240 | "io.read", 241 | "io.write", 242 | "io.flush", 243 | "io.input", 244 | "io.output", 245 | "io.lines", 246 | "io.type", 247 | "os.execute", 248 | "os.remove", 249 | "os.rename", 250 | "os.tmpname", 251 | "os.getenv", 252 | "os.exit", 253 | "os.clock", 254 | "os.date", 255 | "os.time", 256 | "os.difftime", 257 | "os.setlocale", 258 | "debug.getregistry", 259 | "debug.getmetatable", 260 | "debug.setmetatable", 261 | "debug.getfenv", 262 | "debug.setfenv", 263 | "debug.getinfo", 264 | "debug.getlocal", 265 | "debug.setlocal", 266 | "debug.getupvalue", 267 | "debug.setupvalue", 268 | "debug.upvalueid", 269 | "debug.upvaluejoin", 270 | "debug.sethook", 271 | "debug.gethook", 272 | "debug.debug", 273 | "debug.traceback", 274 | "jit.on", 275 | "jit.off", 276 | "jit.flush", 277 | "jit.status", 278 | "jit.attach", 279 | "jit.util.funcinfo", 280 | "jit.util.funcbc", 281 | "jit.util.funck", 282 | "jit.util.funcuvname", 283 | "jit.util.traceinfo", 284 | "jit.util.traceir", 285 | "jit.util.tracek", 286 | "jit.util.tracesnap", 287 | "jit.util.tracemc", 288 | "jit.util.traceexitstub", 289 | "jit.util.ircalladdr", 290 | "jit.opt.start", 291 | "ffi.meta.__index", 292 | "ffi.meta.__newindex", 293 | "ffi.meta.__eq", 294 | "ffi.meta.__len", 295 | "ffi.meta.__lt", 296 | "ffi.meta.__le", 297 | "ffi.meta.__concat", 298 | "ffi.meta.__call", 299 | "ffi.meta.__add", 300 | "ffi.meta.__sub", 301 | "ffi.meta.__mul", 302 | "ffi.meta.__div", 303 | "ffi.meta.__mod", 304 | "ffi.meta.__pow", 305 | "ffi.meta.__unm", 306 | "ffi.meta.__tostring", 307 | "ffi.meta.__pairs", 308 | "ffi.meta.__ipairs", 309 | "ffi.clib.__index", 310 | "ffi.clib.__newindex", 311 | "ffi.clib.__gc", 312 | "ffi.callback.free", 313 | "ffi.callback.set", 314 | "ffi.cdef", 315 | "ffi.new", 316 | "ffi.cast", 317 | "ffi.typeof", 318 | "ffi.istype", 319 | "ffi.sizeof", 320 | "ffi.alignof", 321 | "ffi.offsetof", 322 | "ffi.errno", 323 | "ffi.string", 324 | "ffi.copy", 325 | "ffi.fill", 326 | "ffi.abi", 327 | "ffi.metatype", 328 | "ffi.gc", 329 | "ffi.load", 330 | } 331 | 332 | -------------------------------------------------------------------------------- /proj.mac/EasyLuaEncryptor.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2272A41B1BA09111005BE13A /* EasyLuaEncryptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2272A4171BA09111005BE13A /* EasyLuaEncryptor.cpp */; settings = {ASSET_TAGS = (); }; }; 11 | 2272A41C1BA09111005BE13A /* xxtea.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2272A4191BA09111005BE13A /* xxtea.cpp */; settings = {ASSET_TAGS = (); }; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | 2272A40A1BA0903F005BE13A /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = /usr/share/man/man1/; 19 | dstSubfolderSpec = 0; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 1; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 2272A40C1BA0903F005BE13A /* EasyLuaEncryptor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = EasyLuaEncryptor; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 2272A4171BA09111005BE13A /* EasyLuaEncryptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EasyLuaEncryptor.cpp; sourceTree = ""; }; 29 | 2272A4191BA09111005BE13A /* xxtea.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xxtea.cpp; sourceTree = ""; }; 30 | 2272A41A1BA09111005BE13A /* xxtea.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xxtea.h; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 2272A4091BA0903F005BE13A /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXFrameworksBuildPhase section */ 42 | 43 | /* Begin PBXGroup section */ 44 | 2272A4031BA0903F005BE13A = { 45 | isa = PBXGroup; 46 | children = ( 47 | 2272A4161BA09111005BE13A /* Classes */, 48 | 2272A40D1BA0903F005BE13A /* Products */, 49 | ); 50 | sourceTree = ""; 51 | }; 52 | 2272A40D1BA0903F005BE13A /* Products */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 2272A40C1BA0903F005BE13A /* EasyLuaEncryptor */, 56 | ); 57 | name = Products; 58 | sourceTree = ""; 59 | }; 60 | 2272A4161BA09111005BE13A /* Classes */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 2272A4171BA09111005BE13A /* EasyLuaEncryptor.cpp */, 64 | 2272A4181BA09111005BE13A /* xxtea */, 65 | ); 66 | name = Classes; 67 | path = ../Classes; 68 | sourceTree = ""; 69 | }; 70 | 2272A4181BA09111005BE13A /* xxtea */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | 2272A4191BA09111005BE13A /* xxtea.cpp */, 74 | 2272A41A1BA09111005BE13A /* xxtea.h */, 75 | ); 76 | path = xxtea; 77 | sourceTree = ""; 78 | }; 79 | /* End PBXGroup section */ 80 | 81 | /* Begin PBXNativeTarget section */ 82 | 2272A40B1BA0903F005BE13A /* EasyLuaEncryptor */ = { 83 | isa = PBXNativeTarget; 84 | buildConfigurationList = 2272A4131BA0903F005BE13A /* Build configuration list for PBXNativeTarget "EasyLuaEncryptor" */; 85 | buildPhases = ( 86 | 2272A4081BA0903F005BE13A /* Sources */, 87 | 2272A4091BA0903F005BE13A /* Frameworks */, 88 | 2272A40A1BA0903F005BE13A /* CopyFiles */, 89 | ); 90 | buildRules = ( 91 | ); 92 | dependencies = ( 93 | ); 94 | name = EasyLuaEncryptor; 95 | productName = EasyLuaEncryptor; 96 | productReference = 2272A40C1BA0903F005BE13A /* EasyLuaEncryptor */; 97 | productType = "com.apple.product-type.tool"; 98 | }; 99 | /* End PBXNativeTarget section */ 100 | 101 | /* Begin PBXProject section */ 102 | 2272A4041BA0903F005BE13A /* Project object */ = { 103 | isa = PBXProject; 104 | attributes = { 105 | LastUpgradeCheck = 0700; 106 | ORGANIZATIONNAME = Xin; 107 | TargetAttributes = { 108 | 2272A40B1BA0903F005BE13A = { 109 | CreatedOnToolsVersion = 7.0; 110 | }; 111 | }; 112 | }; 113 | buildConfigurationList = 2272A4071BA0903F005BE13A /* Build configuration list for PBXProject "EasyLuaEncryptor" */; 114 | compatibilityVersion = "Xcode 3.2"; 115 | developmentRegion = English; 116 | hasScannedForEncodings = 0; 117 | knownRegions = ( 118 | en, 119 | ); 120 | mainGroup = 2272A4031BA0903F005BE13A; 121 | productRefGroup = 2272A40D1BA0903F005BE13A /* Products */; 122 | projectDirPath = ""; 123 | projectRoot = ""; 124 | targets = ( 125 | 2272A40B1BA0903F005BE13A /* EasyLuaEncryptor */, 126 | ); 127 | }; 128 | /* End PBXProject section */ 129 | 130 | /* Begin PBXSourcesBuildPhase section */ 131 | 2272A4081BA0903F005BE13A /* Sources */ = { 132 | isa = PBXSourcesBuildPhase; 133 | buildActionMask = 2147483647; 134 | files = ( 135 | 2272A41C1BA09111005BE13A /* xxtea.cpp in Sources */, 136 | 2272A41B1BA09111005BE13A /* EasyLuaEncryptor.cpp in Sources */, 137 | ); 138 | runOnlyForDeploymentPostprocessing = 0; 139 | }; 140 | /* End PBXSourcesBuildPhase section */ 141 | 142 | /* Begin XCBuildConfiguration section */ 143 | 2272A4111BA0903F005BE13A /* Debug */ = { 144 | isa = XCBuildConfiguration; 145 | buildSettings = { 146 | ALWAYS_SEARCH_USER_PATHS = NO; 147 | CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; 148 | CLANG_CXX_LIBRARY = "libc++"; 149 | CLANG_ENABLE_MODULES = YES; 150 | CLANG_ENABLE_OBJC_ARC = YES; 151 | CLANG_WARN_BOOL_CONVERSION = YES; 152 | CLANG_WARN_CONSTANT_CONVERSION = YES; 153 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 154 | CLANG_WARN_EMPTY_BODY = YES; 155 | CLANG_WARN_ENUM_CONVERSION = YES; 156 | CLANG_WARN_INT_CONVERSION = YES; 157 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 158 | CLANG_WARN_UNREACHABLE_CODE = YES; 159 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 160 | COPY_PHASE_STRIP = NO; 161 | DEBUG_INFORMATION_FORMAT = dwarf; 162 | ENABLE_STRICT_OBJC_MSGSEND = YES; 163 | ENABLE_TESTABILITY = YES; 164 | GCC_DYNAMIC_NO_PIC = NO; 165 | GCC_NO_COMMON_BLOCKS = YES; 166 | GCC_OPTIMIZATION_LEVEL = 0; 167 | GCC_PREPROCESSOR_DEFINITIONS = ( 168 | "DEBUG=1", 169 | "$(inherited)", 170 | ); 171 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 172 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 173 | GCC_WARN_UNDECLARED_SELECTOR = YES; 174 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 175 | GCC_WARN_UNUSED_FUNCTION = YES; 176 | GCC_WARN_UNUSED_VARIABLE = YES; 177 | MACOSX_DEPLOYMENT_TARGET = 10.7; 178 | ONLY_ACTIVE_ARCH = YES; 179 | SDKROOT = macosx; 180 | }; 181 | name = Debug; 182 | }; 183 | 2272A4121BA0903F005BE13A /* Release */ = { 184 | isa = XCBuildConfiguration; 185 | buildSettings = { 186 | ALWAYS_SEARCH_USER_PATHS = NO; 187 | CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; 188 | CLANG_CXX_LIBRARY = "libc++"; 189 | CLANG_ENABLE_MODULES = YES; 190 | CLANG_ENABLE_OBJC_ARC = YES; 191 | CLANG_WARN_BOOL_CONVERSION = YES; 192 | CLANG_WARN_CONSTANT_CONVERSION = YES; 193 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 194 | CLANG_WARN_EMPTY_BODY = YES; 195 | CLANG_WARN_ENUM_CONVERSION = YES; 196 | CLANG_WARN_INT_CONVERSION = YES; 197 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 198 | CLANG_WARN_UNREACHABLE_CODE = YES; 199 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 200 | COPY_PHASE_STRIP = YES; 201 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 202 | ENABLE_NS_ASSERTIONS = NO; 203 | ENABLE_STRICT_OBJC_MSGSEND = YES; 204 | GCC_NO_COMMON_BLOCKS = YES; 205 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 206 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 207 | GCC_WARN_UNDECLARED_SELECTOR = YES; 208 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 209 | GCC_WARN_UNUSED_FUNCTION = YES; 210 | GCC_WARN_UNUSED_VARIABLE = YES; 211 | MACOSX_DEPLOYMENT_TARGET = 10.7; 212 | SDKROOT = macosx; 213 | }; 214 | name = Release; 215 | }; 216 | 2272A4141BA0903F005BE13A /* Debug */ = { 217 | isa = XCBuildConfiguration; 218 | buildSettings = { 219 | PRODUCT_NAME = "$(TARGET_NAME)"; 220 | }; 221 | name = Debug; 222 | }; 223 | 2272A4151BA0903F005BE13A /* Release */ = { 224 | isa = XCBuildConfiguration; 225 | buildSettings = { 226 | PRODUCT_NAME = "$(TARGET_NAME)"; 227 | }; 228 | name = Release; 229 | }; 230 | /* End XCBuildConfiguration section */ 231 | 232 | /* Begin XCConfigurationList section */ 233 | 2272A4071BA0903F005BE13A /* Build configuration list for PBXProject "EasyLuaEncryptor" */ = { 234 | isa = XCConfigurationList; 235 | buildConfigurations = ( 236 | 2272A4111BA0903F005BE13A /* Debug */, 237 | 2272A4121BA0903F005BE13A /* Release */, 238 | ); 239 | defaultConfigurationIsVisible = 0; 240 | defaultConfigurationName = Release; 241 | }; 242 | 2272A4131BA0903F005BE13A /* Build configuration list for PBXNativeTarget "EasyLuaEncryptor" */ = { 243 | isa = XCConfigurationList; 244 | buildConfigurations = ( 245 | 2272A4141BA0903F005BE13A /* Debug */, 246 | 2272A4151BA0903F005BE13A /* Release */, 247 | ); 248 | defaultConfigurationIsVisible = 0; 249 | defaultConfigurationName = Release; 250 | }; 251 | /* End XCConfigurationList section */ 252 | }; 253 | rootObject = 2272A4041BA0903F005BE13A /* Project object */; 254 | } 255 | -------------------------------------------------------------------------------- /Classes/EasyLuaEncryptor.cpp: -------------------------------------------------------------------------------- 1 | // HiddensRemover.cpp : 定义控制台应用程序的入口点。 2 | // 3 | 4 | #if defined(WIN32) 5 | 6 | // Exclude rarely-used stuff from Windows headers 7 | #ifndef WIN32_LEAN_AND_MEAN 8 | #define WIN32_LEAN_AND_MEAN 9 | #endif //WIN32_LEAN_AND_MEAN 10 | 11 | #include 12 | #include 13 | 14 | #ifdef _CRTDBG_MAP_ALLOC 15 | #include 16 | #include 17 | #endif 18 | 19 | #else 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #endif 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #ifndef R_OK 44 | #define R_OK (4) /* Test for read permission. */ 45 | #endif 46 | 47 | #ifndef W_OK 48 | #define W_OK (2) /* Test for write permission. */ 49 | #endif 50 | 51 | #ifndef F_OK 52 | #define F_OK (0) /* Test for existence. */ 53 | #endif 54 | 55 | #ifdef WIN32 56 | #define PATH_SEPARATOR_CHAR '\\' 57 | #define PATH_SEPARATOR_STRING "\\" 58 | #else 59 | #define PATH_SEPARATOR_CHAR '/' 60 | #define PATH_SEPARATOR_STRING "/" 61 | #endif 62 | 63 | using namespace std; 64 | 65 | ////////////////////////////////////////////////////////////////////////// 66 | 67 | #include "xxtea/xxtea.h" 68 | 69 | #define EXEC_BINARY_NAME "EasyLuaEncryptor" 70 | #define EXEC_BINARY_VERSION "0.0.2" 71 | 72 | #define DEFAULT_XXTEA_KEY "2dxLua" 73 | #define DEFAULT_XXTEA_SIGN "XXTEA" 74 | 75 | static bool s_bCompileToByteCode = false; 76 | static string s_strLuaJitPath; 77 | static string s_strKey(DEFAULT_XXTEA_KEY); 78 | static string s_strSign(DEFAULT_XXTEA_SIGN); 79 | static const char * XXTEA_KEY = nullptr; 80 | static size_t XXTEA_KEY_LENGTH = 0; 81 | static const char * XXTEA_SIGN = nullptr; 82 | static size_t XXTEA_SIGN_LENGTH = 0; 83 | static vector s_vectorLuaFiles; 84 | 85 | ////////////////////////////////////////////////////////////////////////// 86 | 87 | static void PrintInfo(void) 88 | { 89 | printf("************************************\r\n"); 90 | printf("* %s Ver. %s\r\n", EXEC_BINARY_NAME, EXEC_BINARY_VERSION); 91 | printf("* Powered by Xin Zhang\r\n"); 92 | printf("* %s %s\r\n", __TIME__, __DATE__); 93 | printf("*\r\n"); 94 | printf("* Usage:\r\n"); 95 | printf("* ------\r\n"); 96 | printf("* %s [options] \r\n", EXEC_BINARY_NAME); 97 | printf("* --compile Compile to LuaJIT bytecode.\r\n"); 98 | printf("* -key Key Set XXTEA key.\r\n"); 99 | printf("* -sign Sign Set XXTEA sign.\r\n"); 100 | printf("************************************\r\n"); 101 | } 102 | 103 | static void SearchLuaFilesInDirectory(string & strPath) 104 | { 105 | #ifdef WIN32 106 | 107 | string strToScan = strPath + "*.*"; 108 | WIN32_FIND_DATAA FindFileData = { 0 }; 109 | HANDLE hFind = ::FindFirstFileA(strToScan.c_str(), &FindFileData); 110 | 111 | if (INVALID_HANDLE_VALUE == hFind) 112 | { 113 | printf("Cannot be accessed: %s\r\n", strPath.c_str()); 114 | return; 115 | } 116 | 117 | while (TRUE) 118 | { 119 | string strFileName = FindFileData.cFileName; 120 | 121 | if ('.' == strFileName[0]) 122 | { 123 | // 124 | } 125 | else 126 | { 127 | bool bIsDir = (0 != (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)); 128 | 129 | if (bIsDir) 130 | { 131 | string strSubDir = strPath + strFileName + PATH_SEPARATOR_STRING; 132 | SearchLuaFilesInDirectory(strSubDir); 133 | } 134 | else if (strFileName.length() > 4) 135 | { 136 | string strSubFile = strPath + strFileName; 137 | const char * pLast4Chars = &strSubFile.at(strSubFile.length() - 4); 138 | 139 | if (0 == memcmp(pLast4Chars, ".lua", 4)) 140 | { 141 | s_vectorLuaFiles.push_back(strSubFile); 142 | } 143 | } 144 | } 145 | 146 | if (!FindNextFileA(hFind, &FindFileData)) 147 | { 148 | break; 149 | } 150 | } 151 | 152 | FindClose(hFind); 153 | 154 | #else 155 | 156 | DIR * dir; 157 | struct dirent * entry; 158 | struct stat statbuf; 159 | 160 | if (!(dir = opendir(strPath.c_str()))) 161 | { 162 | return; 163 | } 164 | 165 | while ((entry = readdir(dir))) 166 | { 167 | string strFileName = entry->d_name; 168 | 169 | if ('.' == strFileName[0]) 170 | { 171 | // 172 | } 173 | else 174 | { 175 | string strSub = strPath + entry->d_name; 176 | 177 | lstat(strSub.c_str(), &statbuf); 178 | 179 | bool bIsDir = S_ISDIR(statbuf.st_mode); 180 | 181 | if (bIsDir) 182 | { 183 | strSub += PATH_SEPARATOR_STRING; 184 | SearchLuaFilesInDirectory(strSub); 185 | } 186 | else if (strFileName.length() > 4) 187 | { 188 | const char * pLast4Chars = &strSub.at(strSub.length() - 4); 189 | 190 | if (0 == memcmp(pLast4Chars, ".lua", 4)) 191 | { 192 | s_vectorLuaFiles.push_back(strSub); 193 | } 194 | } 195 | } 196 | } 197 | 198 | closedir(dir); 199 | 200 | #endif 201 | } 202 | 203 | static unsigned char * ReadFile(const char * szFilePath, size_t * pFileLength) 204 | { 205 | if (pFileLength) 206 | { 207 | pFileLength[0] = 0; 208 | } 209 | else 210 | { 211 | return nullptr; 212 | } 213 | 214 | ////////////////////////////////////////////////////////////////////////// 215 | 216 | if (!szFilePath || !szFilePath[0]) 217 | { 218 | return nullptr; 219 | } 220 | 221 | ////////////////////////////////////////////////////////////////////////// 222 | 223 | FILE * fileToRead = fopen(szFilePath, "rb"); 224 | 225 | if (!fileToRead) 226 | { 227 | printf("%s: fopen error.\r\n", __FUNCTION__); 228 | 229 | return nullptr; 230 | } 231 | 232 | ////////////////////////////////////////////////////////////////////////// 233 | 234 | int nFeekResult = fseek(fileToRead, 0, SEEK_END); 235 | long nFileSize = ftell(fileToRead); 236 | unsigned char * pBuffer = nullptr; 237 | 238 | if (0 != nFeekResult) 239 | { 240 | printf("%s: fseek error.\r\n", __FUNCTION__); 241 | } 242 | else if (nFileSize < 0) 243 | { 244 | printf("%s: ftell error.\r\n", __FUNCTION__); 245 | } 246 | else 247 | { 248 | pFileLength[0] = nFileSize; 249 | 250 | if ((pBuffer = (unsigned char *)malloc(sizeof(unsigned char) * (nFileSize + 1)))) 251 | { 252 | if (nFileSize) 253 | { 254 | fseek(fileToRead, 0, SEEK_SET); 255 | 256 | if (nFileSize == fread(pBuffer, sizeof(unsigned char), nFileSize, fileToRead)) 257 | { 258 | pBuffer[nFileSize] = 0; 259 | } 260 | else 261 | { 262 | printf("%s: fread error.\r\n", __FUNCTION__); 263 | free(pBuffer); 264 | pBuffer = nullptr; 265 | } 266 | } 267 | else 268 | { 269 | // Empty file won't be read. 270 | pBuffer[nFileSize] = 0; 271 | } 272 | } 273 | else 274 | { 275 | printf("%s: malloc error.\r\n", __FUNCTION__); 276 | } 277 | } 278 | 279 | fclose(fileToRead); 280 | 281 | return pBuffer; 282 | } 283 | 284 | static bool WriteFile(const char * szFilePath, const unsigned char * pDataToWrite, size_t nFileLength) 285 | { 286 | if (!szFilePath || !szFilePath[0]) 287 | { 288 | return false; 289 | } 290 | 291 | ////////////////////////////////////////////////////////////////////////// 292 | 293 | FILE * fileToWrite = fopen(szFilePath, "wb"); 294 | 295 | if (!fileToWrite) 296 | { 297 | printf("%s: fopen error.\r\n", __FUNCTION__); 298 | 299 | return false; 300 | } 301 | 302 | ////////////////////////////////////////////////////////////////////////// 303 | 304 | bool bRet = false; 305 | 306 | if (nFileLength && pDataToWrite) 307 | { 308 | if (nFileLength == fwrite(pDataToWrite, sizeof(unsigned char), nFileLength, fileToWrite)) 309 | { 310 | bRet = true; 311 | } 312 | else 313 | { 314 | printf("%s: fwrite error.\r\n", __FUNCTION__); 315 | } 316 | } 317 | else 318 | { 319 | printf("%s: Nothing to write.\r\n", __FUNCTION__); 320 | bRet = true; 321 | } 322 | 323 | fclose(fileToWrite); 324 | 325 | return bRet; 326 | } 327 | 328 | bool Encrypt(string & strLuaFile) 329 | { 330 | printf("%s\r\n", strLuaFile.c_str()); 331 | 332 | string strLuaFileFinal = strLuaFile; 333 | 334 | #ifdef WIN32 335 | if (s_bCompileToByteCode) 336 | { 337 | STARTUPINFO si = { 0 }; 338 | PROCESS_INFORMATION pi = { 0 }; 339 | string strCmdLuaJit = "\"" + s_strLuaJitPath + "\" -b \"" + strLuaFile + "\" \"" + strLuaFile + "c\""; 340 | 341 | #if defined(DEBUG) || defined(_DEBUG) 342 | printf("%s\r\n", strCmdLuaJit.c_str()); 343 | #endif 344 | 345 | si.cb = sizeof(STARTUPINFO); 346 | GetStartupInfo(&si); 347 | 348 | BOOL bRet = CreateProcessA(NULL, (char *)(strCmdLuaJit.c_str()), NULL, NULL, FALSE, NULL, NULL, NULL, &si, &pi); // 创建子进程 349 | DWORD dwExitCode = 99999; 350 | 351 | if (bRet) // 输入信息 352 | { 353 | CloseHandle(pi.hThread); 354 | WaitForSingleObject(pi.hProcess, INFINITE); 355 | GetExitCodeProcess(pi.hProcess, &dwExitCode); 356 | CloseHandle(pi.hProcess); 357 | } 358 | else 359 | { 360 | printf("Compile failed: %s\r\n", strLuaFile.c_str()); 361 | return false; 362 | } 363 | 364 | if (0 == dwExitCode && -1 != remove(strLuaFile.c_str())) 365 | { 366 | strLuaFileFinal += "c"; 367 | } 368 | else 369 | { 370 | printf("Compile failed: %s\r\n", strLuaFile.c_str()); 371 | return false; 372 | } 373 | } 374 | #endif 375 | 376 | const char * szLuaFile = strLuaFileFinal.c_str(); 377 | size_t nFileLength; 378 | unsigned char * pFileContent = ReadFile(szLuaFile, &nFileLength); 379 | 380 | if (!pFileContent) 381 | { 382 | return false; 383 | } 384 | 385 | if (nFileLength >= XXTEA_SIGN_LENGTH && 0 == memcmp(pFileContent, XXTEA_SIGN, XXTEA_SIGN_LENGTH)) 386 | { 387 | free(pFileContent); 388 | pFileContent = nullptr; 389 | 390 | printf("%s already encrypted.\r\n", szLuaFile); 391 | 392 | return false; 393 | } 394 | 395 | xxtea_long nEncryptedDataLength; 396 | unsigned char * pEncryptedData = xxtea_encrypt(pFileContent, (xxtea_long)nFileLength, (unsigned char *)XXTEA_KEY, XXTEA_KEY_LENGTH, &nEncryptedDataLength); 397 | 398 | free(pFileContent); 399 | pFileContent = nullptr; 400 | 401 | if (!pEncryptedData) 402 | { 403 | return false; 404 | } 405 | 406 | unsigned char * pDataToWrite = (unsigned char *)malloc(XXTEA_SIGN_LENGTH + nEncryptedDataLength); 407 | 408 | if (!pDataToWrite) 409 | { 410 | free(pEncryptedData); 411 | pEncryptedData = nullptr; 412 | 413 | return false; 414 | } 415 | 416 | memcpy(pDataToWrite, XXTEA_SIGN, XXTEA_SIGN_LENGTH); 417 | memcpy(pDataToWrite + XXTEA_SIGN_LENGTH, pEncryptedData, nEncryptedDataLength); 418 | 419 | free(pEncryptedData); 420 | pEncryptedData = nullptr; 421 | 422 | bool bRet = WriteFile(szLuaFile, pDataToWrite, XXTEA_SIGN_LENGTH + nEncryptedDataLength); 423 | 424 | free(pDataToWrite); 425 | pDataToWrite = nullptr; 426 | 427 | return bRet; 428 | } 429 | 430 | int main(int argc, char * argv[]) 431 | { 432 | PrintInfo(); 433 | 434 | string strRoot = "." PATH_SEPARATOR_STRING;; 435 | 436 | if (argc > 1) 437 | { 438 | for (int i = 1; i < argc; i++) 439 | { 440 | string strArg(argv[i]); 441 | 442 | if ("--compile" == strArg) 443 | { 444 | s_bCompileToByteCode = true; 445 | 446 | #ifdef WIN32 447 | char * buf = (char *)malloc(600); 448 | GetModuleFileNameA(NULL, buf, 600); //得到当前模块路径 449 | char * pLastSlash = strrchr(buf, '\\'); 450 | strcpy(pLastSlash + 1, "luajit.exe"); 451 | printf("LuaJit path: %s\r\n", buf); 452 | s_strLuaJitPath = buf; 453 | free(buf); 454 | #endif 455 | } 456 | else if ("-key" == strArg) 457 | { 458 | if (i >= argc - 1) 459 | { 460 | return -1; 461 | } 462 | else 463 | { 464 | s_strKey = argv[++i]; 465 | } 466 | } 467 | else if ("-sign" == strArg) 468 | { 469 | if (i >= argc - 1) 470 | { 471 | return -1; 472 | } 473 | else 474 | { 475 | s_strSign = argv[++i]; 476 | } 477 | } 478 | else 479 | { 480 | strRoot = strArg; 481 | } 482 | } 483 | } 484 | 485 | XXTEA_KEY = &s_strKey.at(0); 486 | XXTEA_KEY_LENGTH = s_strKey.length(); 487 | XXTEA_SIGN = &s_strSign.at(0); 488 | XXTEA_SIGN_LENGTH = s_strSign.length(); 489 | 490 | char cLastChar = strRoot[strRoot.length() - 1]; 491 | 492 | if (PATH_SEPARATOR_CHAR != cLastChar && '/' != cLastChar) 493 | { 494 | strRoot += PATH_SEPARATOR_STRING; 495 | } 496 | 497 | if (-1 != access(strRoot.c_str(), R_OK)) 498 | { 499 | SearchLuaFilesInDirectory(strRoot); 500 | } 501 | else 502 | { 503 | return -1; 504 | } 505 | 506 | size_t nFileCount = s_vectorLuaFiles.size(); 507 | const unsigned int nCpuCoreNumber = thread::hardware_concurrency(); 508 | bool * bThreadEnds = new bool[nCpuCoreNumber]; 509 | 510 | for (unsigned int nCurrentThreadNumber = 0; nCurrentThreadNumber < nCpuCoreNumber; nCurrentThreadNumber++) 511 | { 512 | bThreadEnds[nCurrentThreadNumber] = false; 513 | 514 | std::thread([nCurrentThreadNumber, nCpuCoreNumber, nFileCount, &bThreadEnds](void) 515 | { 516 | unsigned int nCurrentLuaFileNumber = nCurrentThreadNumber; 517 | 518 | while (nCurrentLuaFileNumber < nFileCount) 519 | { 520 | if (!Encrypt(s_vectorLuaFiles[nCurrentLuaFileNumber])) 521 | { 522 | printf("Failed: %s\r\n", s_vectorLuaFiles[nCurrentLuaFileNumber].c_str()); 523 | } 524 | 525 | nCurrentLuaFileNumber += nCpuCoreNumber; 526 | } 527 | 528 | bThreadEnds[nCurrentThreadNumber] = true; 529 | }).detach(); 530 | } 531 | 532 | while (true) 533 | { 534 | this_thread::sleep_for(chrono::milliseconds(100)); 535 | 536 | bool bAllThreadsEnd = true; 537 | 538 | for (unsigned int nCurrentThreadNumber = 0; nCurrentThreadNumber < nCpuCoreNumber; nCurrentThreadNumber++) 539 | { 540 | bAllThreadsEnd &= bThreadEnds[nCurrentThreadNumber]; 541 | 542 | if (!bAllThreadsEnd) 543 | { 544 | break; 545 | } 546 | } 547 | 548 | if (bAllThreadsEnd) 549 | { 550 | break; 551 | } 552 | } 553 | 554 | delete[] bThreadEnds; 555 | 556 | #if defined(WIN32) && (defined(DEBUG) || defined(_DEBUG)) 557 | getchar(); 558 | #endif 559 | 560 | return 0; 561 | } -------------------------------------------------------------------------------- /proj.win32/lua/jit/dis_mips.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT MIPS disassembler module. 3 | -- 4 | -- Copyright (C) 2005-2013 Mike Pall. All rights reserved. 5 | -- Released under the MIT/X license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- This is a helper module used by the LuaJIT machine code dumper module. 8 | -- 9 | -- It disassembles all standard MIPS32R1/R2 instructions. 10 | -- Default mode is big-endian, but see: dis_mipsel.lua 11 | ------------------------------------------------------------------------------ 12 | 13 | local type = type 14 | local sub, byte, format = string.sub, string.byte, string.format 15 | local match, gmatch, gsub = string.match, string.gmatch, string.gsub 16 | local concat = table.concat 17 | local bit = require("bit") 18 | local band, bor, tohex = bit.band, bit.bor, bit.tohex 19 | local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift 20 | 21 | ------------------------------------------------------------------------------ 22 | -- Primary and extended opcode maps 23 | ------------------------------------------------------------------------------ 24 | 25 | local map_movci = { shift = 16, mask = 1, [0] = "movfDSC", "movtDSC", } 26 | local map_srl = { shift = 21, mask = 1, [0] = "srlDTA", "rotrDTA", } 27 | local map_srlv = { shift = 6, mask = 1, [0] = "srlvDTS", "rotrvDTS", } 28 | 29 | local map_special = { 30 | shift = 0, mask = 63, 31 | [0] = { shift = 0, mask = -1, [0] = "nop", _ = "sllDTA" }, 32 | map_movci, map_srl, "sraDTA", 33 | "sllvDTS", false, map_srlv, "sravDTS", 34 | "jrS", "jalrD1S", "movzDST", "movnDST", 35 | "syscallY", "breakY", false, "sync", 36 | "mfhiD", "mthiS", "mfloD", "mtloS", 37 | false, false, false, false, 38 | "multST", "multuST", "divST", "divuST", 39 | false, false, false, false, 40 | "addDST", "addu|moveDST0", "subDST", "subu|neguDS0T", 41 | "andDST", "orDST", "xorDST", "nor|notDST0", 42 | false, false, "sltDST", "sltuDST", 43 | false, false, false, false, 44 | "tgeSTZ", "tgeuSTZ", "tltSTZ", "tltuSTZ", 45 | "teqSTZ", false, "tneSTZ", 46 | } 47 | 48 | local map_special2 = { 49 | shift = 0, mask = 63, 50 | [0] = "maddST", "madduST", "mulDST", false, 51 | "msubST", "msubuST", 52 | [32] = "clzDS", [33] = "cloDS", 53 | [63] = "sdbbpY", 54 | } 55 | 56 | local map_bshfl = { 57 | shift = 6, mask = 31, 58 | [2] = "wsbhDT", 59 | [16] = "sebDT", 60 | [24] = "sehDT", 61 | } 62 | 63 | local map_special3 = { 64 | shift = 0, mask = 63, 65 | [0] = "extTSAK", [4] = "insTSAL", 66 | [32] = map_bshfl, 67 | [59] = "rdhwrTD", 68 | } 69 | 70 | local map_regimm = { 71 | shift = 16, mask = 31, 72 | [0] = "bltzSB", "bgezSB", "bltzlSB", "bgezlSB", 73 | false, false, false, false, 74 | "tgeiSI", "tgeiuSI", "tltiSI", "tltiuSI", 75 | "teqiSI", false, "tneiSI", false, 76 | "bltzalSB", "bgezalSB", "bltzallSB", "bgezallSB", 77 | false, false, false, false, 78 | false, false, false, false, 79 | false, false, false, "synciSO", 80 | } 81 | 82 | local map_cop0 = { 83 | shift = 25, mask = 1, 84 | [0] = { 85 | shift = 21, mask = 15, 86 | [0] = "mfc0TDW", [4] = "mtc0TDW", 87 | [10] = "rdpgprDT", 88 | [11] = { shift = 5, mask = 1, [0] = "diT0", "eiT0", }, 89 | [14] = "wrpgprDT", 90 | }, { 91 | shift = 0, mask = 63, 92 | [1] = "tlbr", [2] = "tlbwi", [6] = "tlbwr", [8] = "tlbp", 93 | [24] = "eret", [31] = "deret", 94 | [32] = "wait", 95 | }, 96 | } 97 | 98 | local map_cop1s = { 99 | shift = 0, mask = 63, 100 | [0] = "add.sFGH", "sub.sFGH", "mul.sFGH", "div.sFGH", 101 | "sqrt.sFG", "abs.sFG", "mov.sFG", "neg.sFG", 102 | "round.l.sFG", "trunc.l.sFG", "ceil.l.sFG", "floor.l.sFG", 103 | "round.w.sFG", "trunc.w.sFG", "ceil.w.sFG", "floor.w.sFG", 104 | false, 105 | { shift = 16, mask = 1, [0] = "movf.sFGC", "movt.sFGC" }, 106 | "movz.sFGT", "movn.sFGT", 107 | false, "recip.sFG", "rsqrt.sFG", false, 108 | false, false, false, false, 109 | false, false, false, false, 110 | false, "cvt.d.sFG", false, false, 111 | "cvt.w.sFG", "cvt.l.sFG", "cvt.ps.sFGH", false, 112 | false, false, false, false, 113 | false, false, false, false, 114 | "c.f.sVGH", "c.un.sVGH", "c.eq.sVGH", "c.ueq.sVGH", 115 | "c.olt.sVGH", "c.ult.sVGH", "c.ole.sVGH", "c.ule.sVGH", 116 | "c.sf.sVGH", "c.ngle.sVGH", "c.seq.sVGH", "c.ngl.sVGH", 117 | "c.lt.sVGH", "c.nge.sVGH", "c.le.sVGH", "c.ngt.sVGH", 118 | } 119 | 120 | local map_cop1d = { 121 | shift = 0, mask = 63, 122 | [0] = "add.dFGH", "sub.dFGH", "mul.dFGH", "div.dFGH", 123 | "sqrt.dFG", "abs.dFG", "mov.dFG", "neg.dFG", 124 | "round.l.dFG", "trunc.l.dFG", "ceil.l.dFG", "floor.l.dFG", 125 | "round.w.dFG", "trunc.w.dFG", "ceil.w.dFG", "floor.w.dFG", 126 | false, 127 | { shift = 16, mask = 1, [0] = "movf.dFGC", "movt.dFGC" }, 128 | "movz.dFGT", "movn.dFGT", 129 | false, "recip.dFG", "rsqrt.dFG", false, 130 | false, false, false, false, 131 | false, false, false, false, 132 | "cvt.s.dFG", false, false, false, 133 | "cvt.w.dFG", "cvt.l.dFG", false, false, 134 | false, false, false, false, 135 | false, false, false, false, 136 | "c.f.dVGH", "c.un.dVGH", "c.eq.dVGH", "c.ueq.dVGH", 137 | "c.olt.dVGH", "c.ult.dVGH", "c.ole.dVGH", "c.ule.dVGH", 138 | "c.df.dVGH", "c.ngle.dVGH", "c.deq.dVGH", "c.ngl.dVGH", 139 | "c.lt.dVGH", "c.nge.dVGH", "c.le.dVGH", "c.ngt.dVGH", 140 | } 141 | 142 | local map_cop1ps = { 143 | shift = 0, mask = 63, 144 | [0] = "add.psFGH", "sub.psFGH", "mul.psFGH", false, 145 | false, "abs.psFG", "mov.psFG", "neg.psFG", 146 | false, false, false, false, 147 | false, false, false, false, 148 | false, 149 | { shift = 16, mask = 1, [0] = "movf.psFGC", "movt.psFGC" }, 150 | "movz.psFGT", "movn.psFGT", 151 | false, false, false, false, 152 | false, false, false, false, 153 | false, false, false, false, 154 | "cvt.s.puFG", false, false, false, 155 | false, false, false, false, 156 | "cvt.s.plFG", false, false, false, 157 | "pll.psFGH", "plu.psFGH", "pul.psFGH", "puu.psFGH", 158 | "c.f.psVGH", "c.un.psVGH", "c.eq.psVGH", "c.ueq.psVGH", 159 | "c.olt.psVGH", "c.ult.psVGH", "c.ole.psVGH", "c.ule.psVGH", 160 | "c.psf.psVGH", "c.ngle.psVGH", "c.pseq.psVGH", "c.ngl.psVGH", 161 | "c.lt.psVGH", "c.nge.psVGH", "c.le.psVGH", "c.ngt.psVGH", 162 | } 163 | 164 | local map_cop1w = { 165 | shift = 0, mask = 63, 166 | [32] = "cvt.s.wFG", [33] = "cvt.d.wFG", 167 | } 168 | 169 | local map_cop1l = { 170 | shift = 0, mask = 63, 171 | [32] = "cvt.s.lFG", [33] = "cvt.d.lFG", 172 | } 173 | 174 | local map_cop1bc = { 175 | shift = 16, mask = 3, 176 | [0] = "bc1fCB", "bc1tCB", "bc1flCB", "bc1tlCB", 177 | } 178 | 179 | local map_cop1 = { 180 | shift = 21, mask = 31, 181 | [0] = "mfc1TG", false, "cfc1TG", "mfhc1TG", 182 | "mtc1TG", false, "ctc1TG", "mthc1TG", 183 | map_cop1bc, false, false, false, 184 | false, false, false, false, 185 | map_cop1s, map_cop1d, false, false, 186 | map_cop1w, map_cop1l, map_cop1ps, 187 | } 188 | 189 | local map_cop1x = { 190 | shift = 0, mask = 63, 191 | [0] = "lwxc1FSX", "ldxc1FSX", false, false, 192 | false, "luxc1FSX", false, false, 193 | "swxc1FSX", "sdxc1FSX", false, false, 194 | false, "suxc1FSX", false, "prefxMSX", 195 | false, false, false, false, 196 | false, false, false, false, 197 | false, false, false, false, 198 | false, false, "alnv.psFGHS", false, 199 | "madd.sFRGH", "madd.dFRGH", false, false, 200 | false, false, "madd.psFRGH", false, 201 | "msub.sFRGH", "msub.dFRGH", false, false, 202 | false, false, "msub.psFRGH", false, 203 | "nmadd.sFRGH", "nmadd.dFRGH", false, false, 204 | false, false, "nmadd.psFRGH", false, 205 | "nmsub.sFRGH", "nmsub.dFRGH", false, false, 206 | false, false, "nmsub.psFRGH", false, 207 | } 208 | 209 | local map_pri = { 210 | [0] = map_special, map_regimm, "jJ", "jalJ", 211 | "beq|beqz|bST00B", "bne|bnezST0B", "blezSB", "bgtzSB", 212 | "addiTSI", "addiu|liTS0I", "sltiTSI", "sltiuTSI", 213 | "andiTSU", "ori|liTS0U", "xoriTSU", "luiTU", 214 | map_cop0, map_cop1, false, map_cop1x, 215 | "beql|beqzlST0B", "bnel|bnezlST0B", "blezlSB", "bgtzlSB", 216 | false, false, false, false, 217 | map_special2, false, false, map_special3, 218 | "lbTSO", "lhTSO", "lwlTSO", "lwTSO", 219 | "lbuTSO", "lhuTSO", "lwrTSO", false, 220 | "sbTSO", "shTSO", "swlTSO", "swTSO", 221 | false, false, "swrTSO", "cacheNSO", 222 | "llTSO", "lwc1HSO", "lwc2TSO", "prefNSO", 223 | false, "ldc1HSO", "ldc2TSO", false, 224 | "scTSO", "swc1HSO", "swc2TSO", false, 225 | false, "sdc1HSO", "sdc2TSO", false, 226 | } 227 | 228 | ------------------------------------------------------------------------------ 229 | 230 | local map_gpr = { 231 | [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 232 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 233 | "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 234 | "r24", "r25", "r26", "r27", "r28", "sp", "r30", "ra", 235 | } 236 | 237 | ------------------------------------------------------------------------------ 238 | 239 | -- Output a nicely formatted line with an opcode and operands. 240 | local function putop(ctx, text, operands) 241 | local pos = ctx.pos 242 | local extra = "" 243 | if ctx.rel then 244 | local sym = ctx.symtab[ctx.rel] 245 | if sym then extra = "\t->"..sym end 246 | end 247 | if ctx.hexdump > 0 then 248 | ctx.out(format("%08x %s %-7s %s%s\n", 249 | ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) 250 | else 251 | ctx.out(format("%08x %-7s %s%s\n", 252 | ctx.addr+pos, text, concat(operands, ", "), extra)) 253 | end 254 | ctx.pos = pos + 4 255 | end 256 | 257 | -- Fallback for unknown opcodes. 258 | local function unknown(ctx) 259 | return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) 260 | end 261 | 262 | local function get_be(ctx) 263 | local pos = ctx.pos 264 | local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) 265 | return bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3) 266 | end 267 | 268 | local function get_le(ctx) 269 | local pos = ctx.pos 270 | local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) 271 | return bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) 272 | end 273 | 274 | -- Disassemble a single instruction. 275 | local function disass_ins(ctx) 276 | local op = ctx:get() 277 | local operands = {} 278 | local last = nil 279 | ctx.op = op 280 | ctx.rel = nil 281 | 282 | local opat = map_pri[rshift(op, 26)] 283 | while type(opat) ~= "string" do 284 | if not opat then return unknown(ctx) end 285 | opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ 286 | end 287 | local name, pat = match(opat, "^([a-z0-9_.]*)(.*)") 288 | local altname, pat2 = match(pat, "|([a-z0-9_.|]*)(.*)") 289 | if altname then pat = pat2 end 290 | 291 | for p in gmatch(pat, ".") do 292 | local x = nil 293 | if p == "S" then 294 | x = map_gpr[band(rshift(op, 21), 31)] 295 | elseif p == "T" then 296 | x = map_gpr[band(rshift(op, 16), 31)] 297 | elseif p == "D" then 298 | x = map_gpr[band(rshift(op, 11), 31)] 299 | elseif p == "F" then 300 | x = "f"..band(rshift(op, 6), 31) 301 | elseif p == "G" then 302 | x = "f"..band(rshift(op, 11), 31) 303 | elseif p == "H" then 304 | x = "f"..band(rshift(op, 16), 31) 305 | elseif p == "R" then 306 | x = "f"..band(rshift(op, 21), 31) 307 | elseif p == "A" then 308 | x = band(rshift(op, 6), 31) 309 | elseif p == "M" then 310 | x = band(rshift(op, 11), 31) 311 | elseif p == "N" then 312 | x = band(rshift(op, 16), 31) 313 | elseif p == "C" then 314 | x = band(rshift(op, 18), 7) 315 | if x == 0 then x = nil end 316 | elseif p == "K" then 317 | x = band(rshift(op, 11), 31) + 1 318 | elseif p == "L" then 319 | x = band(rshift(op, 11), 31) - last + 1 320 | elseif p == "I" then 321 | x = arshift(lshift(op, 16), 16) 322 | elseif p == "U" then 323 | x = band(op, 0xffff) 324 | elseif p == "O" then 325 | local disp = arshift(lshift(op, 16), 16) 326 | operands[#operands] = format("%d(%s)", disp, last) 327 | elseif p == "X" then 328 | local index = map_gpr[band(rshift(op, 16), 31)] 329 | operands[#operands] = format("%s(%s)", index, last) 330 | elseif p == "B" then 331 | x = ctx.addr + ctx.pos + arshift(lshift(op, 16), 16)*4 + 4 332 | ctx.rel = x 333 | x = "0x"..tohex(x) 334 | elseif p == "J" then 335 | x = band(ctx.addr + ctx.pos, 0xf0000000) + band(op, 0x03ffffff)*4 336 | ctx.rel = x 337 | x = "0x"..tohex(x) 338 | elseif p == "V" then 339 | x = band(rshift(op, 8), 7) 340 | if x == 0 then x = nil end 341 | elseif p == "W" then 342 | x = band(op, 7) 343 | if x == 0 then x = nil end 344 | elseif p == "Y" then 345 | x = band(rshift(op, 6), 0x000fffff) 346 | if x == 0 then x = nil end 347 | elseif p == "Z" then 348 | x = band(rshift(op, 6), 1023) 349 | if x == 0 then x = nil end 350 | elseif p == "0" then 351 | if last == "r0" or last == 0 then 352 | local n = #operands 353 | operands[n] = nil 354 | last = operands[n-1] 355 | if altname then 356 | local a1, a2 = match(altname, "([^|]*)|(.*)") 357 | if a1 then name, altname = a1, a2 358 | else name = altname end 359 | end 360 | end 361 | elseif p == "1" then 362 | if last == "ra" then 363 | operands[#operands] = nil 364 | end 365 | else 366 | assert(false) 367 | end 368 | if x then operands[#operands+1] = x; last = x end 369 | end 370 | 371 | return putop(ctx, name, operands) 372 | end 373 | 374 | ------------------------------------------------------------------------------ 375 | 376 | -- Disassemble a block of code. 377 | local function disass_block(ctx, ofs, len) 378 | if not ofs then ofs = 0 end 379 | local stop = len and ofs+len or #ctx.code 380 | stop = stop - stop % 4 381 | ctx.pos = ofs - ofs % 4 382 | ctx.rel = nil 383 | while ctx.pos < stop do disass_ins(ctx) end 384 | end 385 | 386 | -- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). 387 | local function create_(code, addr, out) 388 | local ctx = {} 389 | ctx.code = code 390 | ctx.addr = addr or 0 391 | ctx.out = out or io.write 392 | ctx.symtab = {} 393 | ctx.disass = disass_block 394 | ctx.hexdump = 8 395 | ctx.get = get_be 396 | return ctx 397 | end 398 | 399 | local function create_el_(code, addr, out) 400 | local ctx = create_(code, addr, out) 401 | ctx.get = get_le 402 | return ctx 403 | end 404 | 405 | -- Simple API: disassemble code (a string) at address and output via out. 406 | local function disass_(code, addr, out) 407 | create_(code, addr, out):disass() 408 | end 409 | 410 | local function disass_el_(code, addr, out) 411 | create_el_(code, addr, out):disass() 412 | end 413 | 414 | -- Return register name for RID. 415 | local function regname_(r) 416 | if r < 32 then return map_gpr[r] end 417 | return "f"..(r-32) 418 | end 419 | 420 | -- Public module functions. 421 | module(...) 422 | 423 | create = create_ 424 | create_el = create_el_ 425 | disass = disass_ 426 | disass_el = disass_el_ 427 | regname = regname_ 428 | 429 | -------------------------------------------------------------------------------- /proj.win32/lua/jit/bcsave.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT module to save/list bytecode. 3 | -- 4 | -- Copyright (C) 2005-2013 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- 8 | -- This module saves or lists the bytecode for an input file. 9 | -- It's run by the -b command line option. 10 | -- 11 | ------------------------------------------------------------------------------ 12 | 13 | local jit = require("jit") 14 | assert(jit.version_num == 20001, "LuaJIT core/library version mismatch") 15 | local bit = require("bit") 16 | 17 | -- Symbol name prefix for LuaJIT bytecode. 18 | local LJBC_PREFIX = "luaJIT_BC_" 19 | 20 | ------------------------------------------------------------------------------ 21 | 22 | local function usage() 23 | io.stderr:write[[ 24 | Save LuaJIT bytecode: luajit -b[options] input output 25 | -l Only list bytecode. 26 | -s Strip debug info (default). 27 | -g Keep debug info. 28 | -n name Set module name (default: auto-detect from input name). 29 | -t type Set output file type (default: auto-detect from output name). 30 | -a arch Override architecture for object files (default: native). 31 | -o os Override OS for object files (default: native). 32 | -e chunk Use chunk string as input. 33 | -- Stop handling options. 34 | - Use stdin as input and/or stdout as output. 35 | 36 | File types: c h obj o raw (default) 37 | ]] 38 | os.exit(1) 39 | end 40 | 41 | local function check(ok, ...) 42 | if ok then return ok, ... end 43 | io.stderr:write("luajit: ", ...) 44 | io.stderr:write("\n") 45 | os.exit(1) 46 | end 47 | 48 | local function readfile(input) 49 | if type(input) == "function" then return input end 50 | if input == "-" then input = nil end 51 | return check(loadfile(input)) 52 | end 53 | 54 | local function savefile(name, mode) 55 | if name == "-" then return io.stdout end 56 | return check(io.open(name, mode)) 57 | end 58 | 59 | ------------------------------------------------------------------------------ 60 | 61 | local map_type = { 62 | raw = "raw", c = "c", h = "h", o = "obj", obj = "obj", 63 | } 64 | 65 | local map_arch = { 66 | x86 = true, x64 = true, arm = true, ppc = true, ppcspe = true, 67 | mips = true, mipsel = true, 68 | } 69 | 70 | local map_os = { 71 | linux = true, windows = true, osx = true, freebsd = true, netbsd = true, 72 | openbsd = true, solaris = true, 73 | } 74 | 75 | local function checkarg(str, map, err) 76 | str = string.lower(str) 77 | local s = check(map[str], "unknown ", err) 78 | return s == true and str or s 79 | end 80 | 81 | local function detecttype(str) 82 | local ext = string.match(string.lower(str), "%.(%a+)$") 83 | return map_type[ext] or "raw" 84 | end 85 | 86 | local function checkmodname(str) 87 | check(string.match(str, "^[%w_.%-]+$"), "bad module name") 88 | return string.gsub(str, "[%.%-]", "_") 89 | end 90 | 91 | local function detectmodname(str) 92 | if type(str) == "string" then 93 | local tail = string.match(str, "[^/\\]+$") 94 | if tail then str = tail end 95 | local head = string.match(str, "^(.*)%.[^.]*$") 96 | if head then str = head end 97 | str = string.match(str, "^[%w_.%-]+") 98 | else 99 | str = nil 100 | end 101 | check(str, "cannot derive module name, use -n name") 102 | return string.gsub(str, "[%.%-]", "_") 103 | end 104 | 105 | ------------------------------------------------------------------------------ 106 | 107 | local function bcsave_tail(fp, output, s) 108 | local ok, err = fp:write(s) 109 | if ok and output ~= "-" then ok, err = fp:close() end 110 | check(ok, "cannot write ", output, ": ", err) 111 | end 112 | 113 | local function bcsave_raw(output, s) 114 | local fp = savefile(output, "wb") 115 | bcsave_tail(fp, output, s) 116 | end 117 | 118 | local function bcsave_c(ctx, output, s) 119 | local fp = savefile(output, "w") 120 | if ctx.type == "c" then 121 | fp:write(string.format([[ 122 | #ifdef _cplusplus 123 | extern "C" 124 | #endif 125 | #ifdef _WIN32 126 | __declspec(dllexport) 127 | #endif 128 | const char %s%s[] = { 129 | ]], LJBC_PREFIX, ctx.modname)) 130 | else 131 | fp:write(string.format([[ 132 | #define %s%s_SIZE %d 133 | static const char %s%s[] = { 134 | ]], LJBC_PREFIX, ctx.modname, #s, LJBC_PREFIX, ctx.modname)) 135 | end 136 | local t, n, m = {}, 0, 0 137 | for i=1,#s do 138 | local b = tostring(string.byte(s, i)) 139 | m = m + #b + 1 140 | if m > 78 then 141 | fp:write(table.concat(t, ",", 1, n), ",\n") 142 | n, m = 0, #b + 1 143 | end 144 | n = n + 1 145 | t[n] = b 146 | end 147 | bcsave_tail(fp, output, table.concat(t, ",", 1, n).."\n};\n") 148 | end 149 | 150 | local function bcsave_elfobj(ctx, output, s, ffi) 151 | ffi.cdef[[ 152 | typedef struct { 153 | uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; 154 | uint16_t type, machine; 155 | uint32_t version; 156 | uint32_t entry, phofs, shofs; 157 | uint32_t flags; 158 | uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; 159 | } ELF32header; 160 | typedef struct { 161 | uint8_t emagic[4], eclass, eendian, eversion, eosabi, eabiversion, epad[7]; 162 | uint16_t type, machine; 163 | uint32_t version; 164 | uint64_t entry, phofs, shofs; 165 | uint32_t flags; 166 | uint16_t ehsize, phentsize, phnum, shentsize, shnum, shstridx; 167 | } ELF64header; 168 | typedef struct { 169 | uint32_t name, type, flags, addr, ofs, size, link, info, align, entsize; 170 | } ELF32sectheader; 171 | typedef struct { 172 | uint32_t name, type; 173 | uint64_t flags, addr, ofs, size; 174 | uint32_t link, info; 175 | uint64_t align, entsize; 176 | } ELF64sectheader; 177 | typedef struct { 178 | uint32_t name, value, size; 179 | uint8_t info, other; 180 | uint16_t sectidx; 181 | } ELF32symbol; 182 | typedef struct { 183 | uint32_t name; 184 | uint8_t info, other; 185 | uint16_t sectidx; 186 | uint64_t value, size; 187 | } ELF64symbol; 188 | typedef struct { 189 | ELF32header hdr; 190 | ELF32sectheader sect[6]; 191 | ELF32symbol sym[2]; 192 | uint8_t space[4096]; 193 | } ELF32obj; 194 | typedef struct { 195 | ELF64header hdr; 196 | ELF64sectheader sect[6]; 197 | ELF64symbol sym[2]; 198 | uint8_t space[4096]; 199 | } ELF64obj; 200 | ]] 201 | local symname = LJBC_PREFIX..ctx.modname 202 | local is64, isbe = false, false 203 | if ctx.arch == "x64" then 204 | is64 = true 205 | elseif ctx.arch == "ppc" or ctx.arch == "ppcspe" or ctx.arch == "mips" then 206 | isbe = true 207 | end 208 | 209 | -- Handle different host/target endianess. 210 | local function f32(x) return x end 211 | local f16, fofs = f32, f32 212 | if ffi.abi("be") ~= isbe then 213 | f32 = bit.bswap 214 | function f16(x) return bit.rshift(bit.bswap(x), 16) end 215 | if is64 then 216 | local two32 = ffi.cast("int64_t", 2^32) 217 | function fofs(x) return bit.bswap(x)*two32 end 218 | else 219 | fofs = f32 220 | end 221 | end 222 | 223 | -- Create ELF object and fill in header. 224 | local o = ffi.new(is64 and "ELF64obj" or "ELF32obj") 225 | local hdr = o.hdr 226 | if ctx.os == "bsd" or ctx.os == "other" then -- Determine native hdr.eosabi. 227 | local bf = assert(io.open("/bin/ls", "rb")) 228 | local bs = bf:read(9) 229 | bf:close() 230 | ffi.copy(o, bs, 9) 231 | check(hdr.emagic[0] == 127, "no support for writing native object files") 232 | else 233 | hdr.emagic = "\127ELF" 234 | hdr.eosabi = ({ freebsd=9, netbsd=2, openbsd=12, solaris=6 })[ctx.os] or 0 235 | end 236 | hdr.eclass = is64 and 2 or 1 237 | hdr.eendian = isbe and 2 or 1 238 | hdr.eversion = 1 239 | hdr.type = f16(1) 240 | hdr.machine = f16(({ x86=3, x64=62, arm=40, ppc=20, ppcspe=20, mips=8, mipsel=8 })[ctx.arch]) 241 | if ctx.arch == "mips" or ctx.arch == "mipsel" then 242 | hdr.flags = 0x50001006 243 | end 244 | hdr.version = f32(1) 245 | hdr.shofs = fofs(ffi.offsetof(o, "sect")) 246 | hdr.ehsize = f16(ffi.sizeof(hdr)) 247 | hdr.shentsize = f16(ffi.sizeof(o.sect[0])) 248 | hdr.shnum = f16(6) 249 | hdr.shstridx = f16(2) 250 | 251 | -- Fill in sections and symbols. 252 | local sofs, ofs = ffi.offsetof(o, "space"), 1 253 | for i,name in ipairs{ 254 | ".symtab", ".shstrtab", ".strtab", ".rodata", ".note.GNU-stack", 255 | } do 256 | local sect = o.sect[i] 257 | sect.align = fofs(1) 258 | sect.name = f32(ofs) 259 | ffi.copy(o.space+ofs, name) 260 | ofs = ofs + #name+1 261 | end 262 | o.sect[1].type = f32(2) -- .symtab 263 | o.sect[1].link = f32(3) 264 | o.sect[1].info = f32(1) 265 | o.sect[1].align = fofs(8) 266 | o.sect[1].ofs = fofs(ffi.offsetof(o, "sym")) 267 | o.sect[1].entsize = fofs(ffi.sizeof(o.sym[0])) 268 | o.sect[1].size = fofs(ffi.sizeof(o.sym)) 269 | o.sym[1].name = f32(1) 270 | o.sym[1].sectidx = f16(4) 271 | o.sym[1].size = fofs(#s) 272 | o.sym[1].info = 17 273 | o.sect[2].type = f32(3) -- .shstrtab 274 | o.sect[2].ofs = fofs(sofs) 275 | o.sect[2].size = fofs(ofs) 276 | o.sect[3].type = f32(3) -- .strtab 277 | o.sect[3].ofs = fofs(sofs + ofs) 278 | o.sect[3].size = fofs(#symname+1) 279 | ffi.copy(o.space+ofs+1, symname) 280 | ofs = ofs + #symname + 2 281 | o.sect[4].type = f32(1) -- .rodata 282 | o.sect[4].flags = fofs(2) 283 | o.sect[4].ofs = fofs(sofs + ofs) 284 | o.sect[4].size = fofs(#s) 285 | o.sect[5].type = f32(1) -- .note.GNU-stack 286 | o.sect[5].ofs = fofs(sofs + ofs + #s) 287 | 288 | -- Write ELF object file. 289 | local fp = savefile(output, "wb") 290 | fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) 291 | bcsave_tail(fp, output, s) 292 | end 293 | 294 | local function bcsave_peobj(ctx, output, s, ffi) 295 | ffi.cdef[[ 296 | typedef struct { 297 | uint16_t arch, nsects; 298 | uint32_t time, symtabofs, nsyms; 299 | uint16_t opthdrsz, flags; 300 | } PEheader; 301 | typedef struct { 302 | char name[8]; 303 | uint32_t vsize, vaddr, size, ofs, relocofs, lineofs; 304 | uint16_t nreloc, nline; 305 | uint32_t flags; 306 | } PEsection; 307 | typedef struct __attribute((packed)) { 308 | union { 309 | char name[8]; 310 | uint32_t nameref[2]; 311 | }; 312 | uint32_t value; 313 | int16_t sect; 314 | uint16_t type; 315 | uint8_t scl, naux; 316 | } PEsym; 317 | typedef struct __attribute((packed)) { 318 | uint32_t size; 319 | uint16_t nreloc, nline; 320 | uint32_t cksum; 321 | uint16_t assoc; 322 | uint8_t comdatsel, unused[3]; 323 | } PEsymaux; 324 | typedef struct { 325 | PEheader hdr; 326 | PEsection sect[2]; 327 | // Must be an even number of symbol structs. 328 | PEsym sym0; 329 | PEsymaux sym0aux; 330 | PEsym sym1; 331 | PEsymaux sym1aux; 332 | PEsym sym2; 333 | PEsym sym3; 334 | uint32_t strtabsize; 335 | uint8_t space[4096]; 336 | } PEobj; 337 | ]] 338 | local symname = LJBC_PREFIX..ctx.modname 339 | local is64 = false 340 | if ctx.arch == "x86" then 341 | symname = "_"..symname 342 | elseif ctx.arch == "x64" then 343 | is64 = true 344 | end 345 | local symexport = " /EXPORT:"..symname..",DATA " 346 | 347 | -- The file format is always little-endian. Swap if the host is big-endian. 348 | local function f32(x) return x end 349 | local f16 = f32 350 | if ffi.abi("be") then 351 | f32 = bit.bswap 352 | function f16(x) return bit.rshift(bit.bswap(x), 16) end 353 | end 354 | 355 | -- Create PE object and fill in header. 356 | local o = ffi.new("PEobj") 357 | local hdr = o.hdr 358 | hdr.arch = f16(({ x86=0x14c, x64=0x8664, arm=0x1c0, ppc=0x1f2, mips=0x366, mipsel=0x366 })[ctx.arch]) 359 | hdr.nsects = f16(2) 360 | hdr.symtabofs = f32(ffi.offsetof(o, "sym0")) 361 | hdr.nsyms = f32(6) 362 | 363 | -- Fill in sections and symbols. 364 | o.sect[0].name = ".drectve" 365 | o.sect[0].size = f32(#symexport) 366 | o.sect[0].flags = f32(0x00100a00) 367 | o.sym0.sect = f16(1) 368 | o.sym0.scl = 3 369 | o.sym0.name = ".drectve" 370 | o.sym0.naux = 1 371 | o.sym0aux.size = f32(#symexport) 372 | o.sect[1].name = ".rdata" 373 | o.sect[1].size = f32(#s) 374 | o.sect[1].flags = f32(0x40300040) 375 | o.sym1.sect = f16(2) 376 | o.sym1.scl = 3 377 | o.sym1.name = ".rdata" 378 | o.sym1.naux = 1 379 | o.sym1aux.size = f32(#s) 380 | o.sym2.sect = f16(2) 381 | o.sym2.scl = 2 382 | o.sym2.nameref[1] = f32(4) 383 | o.sym3.sect = f16(-1) 384 | o.sym3.scl = 2 385 | o.sym3.value = f32(1) 386 | o.sym3.name = "@feat.00" -- Mark as SafeSEH compliant. 387 | ffi.copy(o.space, symname) 388 | local ofs = #symname + 1 389 | o.strtabsize = f32(ofs + 4) 390 | o.sect[0].ofs = f32(ffi.offsetof(o, "space") + ofs) 391 | ffi.copy(o.space + ofs, symexport) 392 | ofs = ofs + #symexport 393 | o.sect[1].ofs = f32(ffi.offsetof(o, "space") + ofs) 394 | 395 | -- Write PE object file. 396 | local fp = savefile(output, "wb") 397 | fp:write(ffi.string(o, ffi.sizeof(o)-4096+ofs)) 398 | bcsave_tail(fp, output, s) 399 | end 400 | 401 | local function bcsave_machobj(ctx, output, s, ffi) 402 | ffi.cdef[[ 403 | typedef struct 404 | { 405 | uint32_t magic, cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags; 406 | } mach_header; 407 | typedef struct 408 | { 409 | mach_header; uint32_t reserved; 410 | } mach_header_64; 411 | typedef struct { 412 | uint32_t cmd, cmdsize; 413 | char segname[16]; 414 | uint32_t vmaddr, vmsize, fileoff, filesize; 415 | uint32_t maxprot, initprot, nsects, flags; 416 | } mach_segment_command; 417 | typedef struct { 418 | uint32_t cmd, cmdsize; 419 | char segname[16]; 420 | uint64_t vmaddr, vmsize, fileoff, filesize; 421 | uint32_t maxprot, initprot, nsects, flags; 422 | } mach_segment_command_64; 423 | typedef struct { 424 | char sectname[16], segname[16]; 425 | uint32_t addr, size; 426 | uint32_t offset, align, reloff, nreloc, flags; 427 | uint32_t reserved1, reserved2; 428 | } mach_section; 429 | typedef struct { 430 | char sectname[16], segname[16]; 431 | uint64_t addr, size; 432 | uint32_t offset, align, reloff, nreloc, flags; 433 | uint32_t reserved1, reserved2, reserved3; 434 | } mach_section_64; 435 | typedef struct { 436 | uint32_t cmd, cmdsize, symoff, nsyms, stroff, strsize; 437 | } mach_symtab_command; 438 | typedef struct { 439 | int32_t strx; 440 | uint8_t type, sect; 441 | int16_t desc; 442 | uint32_t value; 443 | } mach_nlist; 444 | typedef struct { 445 | uint32_t strx; 446 | uint8_t type, sect; 447 | uint16_t desc; 448 | uint64_t value; 449 | } mach_nlist_64; 450 | typedef struct 451 | { 452 | uint32_t magic, nfat_arch; 453 | } mach_fat_header; 454 | typedef struct 455 | { 456 | uint32_t cputype, cpusubtype, offset, size, align; 457 | } mach_fat_arch; 458 | typedef struct { 459 | struct { 460 | mach_header hdr; 461 | mach_segment_command seg; 462 | mach_section sec; 463 | mach_symtab_command sym; 464 | } arch[1]; 465 | mach_nlist sym_entry; 466 | uint8_t space[4096]; 467 | } mach_obj; 468 | typedef struct { 469 | struct { 470 | mach_header_64 hdr; 471 | mach_segment_command_64 seg; 472 | mach_section_64 sec; 473 | mach_symtab_command sym; 474 | } arch[1]; 475 | mach_nlist_64 sym_entry; 476 | uint8_t space[4096]; 477 | } mach_obj_64; 478 | typedef struct { 479 | mach_fat_header fat; 480 | mach_fat_arch fat_arch[4]; 481 | struct { 482 | mach_header hdr; 483 | mach_segment_command seg; 484 | mach_section sec; 485 | mach_symtab_command sym; 486 | } arch[4]; 487 | mach_nlist sym_entry; 488 | uint8_t space[4096]; 489 | } mach_fat_obj; 490 | ]] 491 | local symname = '_'..LJBC_PREFIX..ctx.modname 492 | local isfat, is64, align, mobj = false, false, 4, "mach_obj" 493 | if ctx.arch == "x64" then 494 | is64, align, mobj = true, 8, "mach_obj_64" 495 | elseif ctx.arch == "arm" then 496 | isfat, mobj = true, "mach_fat_obj" 497 | else 498 | check(ctx.arch == "x86", "unsupported architecture for OSX") 499 | end 500 | local function aligned(v, a) return bit.band(v+a-1, -a) end 501 | local be32 = bit.bswap -- Mach-O FAT is BE, supported archs are LE. 502 | 503 | -- Create Mach-O object and fill in header. 504 | local o = ffi.new(mobj) 505 | local mach_size = aligned(ffi.offsetof(o, "space")+#symname+2, align) 506 | local cputype = ({ x86={7}, x64={0x01000007}, arm={7,12,12,12} })[ctx.arch] 507 | local cpusubtype = ({ x86={3}, x64={3}, arm={3,6,9,11} })[ctx.arch] 508 | if isfat then 509 | o.fat.magic = be32(0xcafebabe) 510 | o.fat.nfat_arch = be32(#cpusubtype) 511 | end 512 | 513 | -- Fill in sections and symbols. 514 | for i=0,#cpusubtype-1 do 515 | local ofs = 0 516 | if isfat then 517 | local a = o.fat_arch[i] 518 | a.cputype = be32(cputype[i+1]) 519 | a.cpusubtype = be32(cpusubtype[i+1]) 520 | -- Subsequent slices overlap each other to share data. 521 | ofs = ffi.offsetof(o, "arch") + i*ffi.sizeof(o.arch[0]) 522 | a.offset = be32(ofs) 523 | a.size = be32(mach_size-ofs+#s) 524 | end 525 | local a = o.arch[i] 526 | a.hdr.magic = is64 and 0xfeedfacf or 0xfeedface 527 | a.hdr.cputype = cputype[i+1] 528 | a.hdr.cpusubtype = cpusubtype[i+1] 529 | a.hdr.filetype = 1 530 | a.hdr.ncmds = 2 531 | a.hdr.sizeofcmds = ffi.sizeof(a.seg)+ffi.sizeof(a.sec)+ffi.sizeof(a.sym) 532 | a.seg.cmd = is64 and 0x19 or 0x1 533 | a.seg.cmdsize = ffi.sizeof(a.seg)+ffi.sizeof(a.sec) 534 | a.seg.vmsize = #s 535 | a.seg.fileoff = mach_size-ofs 536 | a.seg.filesize = #s 537 | a.seg.maxprot = 1 538 | a.seg.initprot = 1 539 | a.seg.nsects = 1 540 | ffi.copy(a.sec.sectname, "__data") 541 | ffi.copy(a.sec.segname, "__DATA") 542 | a.sec.size = #s 543 | a.sec.offset = mach_size-ofs 544 | a.sym.cmd = 2 545 | a.sym.cmdsize = ffi.sizeof(a.sym) 546 | a.sym.symoff = ffi.offsetof(o, "sym_entry")-ofs 547 | a.sym.nsyms = 1 548 | a.sym.stroff = ffi.offsetof(o, "sym_entry")+ffi.sizeof(o.sym_entry)-ofs 549 | a.sym.strsize = aligned(#symname+2, align) 550 | end 551 | o.sym_entry.type = 0xf 552 | o.sym_entry.sect = 1 553 | o.sym_entry.strx = 1 554 | ffi.copy(o.space+1, symname) 555 | 556 | -- Write Macho-O object file. 557 | local fp = savefile(output, "wb") 558 | fp:write(ffi.string(o, mach_size)) 559 | bcsave_tail(fp, output, s) 560 | end 561 | 562 | local function bcsave_obj(ctx, output, s) 563 | local ok, ffi = pcall(require, "ffi") 564 | check(ok, "FFI library required to write this file type") 565 | if ctx.os == "windows" then 566 | return bcsave_peobj(ctx, output, s, ffi) 567 | elseif ctx.os == "osx" then 568 | return bcsave_machobj(ctx, output, s, ffi) 569 | else 570 | return bcsave_elfobj(ctx, output, s, ffi) 571 | end 572 | end 573 | 574 | ------------------------------------------------------------------------------ 575 | 576 | local function bclist(input, output) 577 | local f = readfile(input) 578 | require("jit.bc").dump(f, savefile(output, "w"), true) 579 | end 580 | 581 | local function bcsave(ctx, input, output) 582 | local f = readfile(input) 583 | local s = string.dump(f, ctx.strip) 584 | local t = ctx.type 585 | if not t then 586 | t = detecttype(output) 587 | ctx.type = t 588 | end 589 | if t == "raw" then 590 | bcsave_raw(output, s) 591 | else 592 | if not ctx.modname then ctx.modname = detectmodname(input) end 593 | if t == "obj" then 594 | bcsave_obj(ctx, output, s) 595 | else 596 | bcsave_c(ctx, output, s) 597 | end 598 | end 599 | end 600 | 601 | local function docmd(...) 602 | local arg = {...} 603 | local n = 1 604 | local list = false 605 | local ctx = { 606 | strip = true, arch = jit.arch, os = string.lower(jit.os), 607 | type = false, modname = false, 608 | } 609 | while n <= #arg do 610 | local a = arg[n] 611 | if type(a) == "string" and string.sub(a, 1, 1) == "-" and a ~= "-" then 612 | table.remove(arg, n) 613 | if a == "--" then break end 614 | for m=2,#a do 615 | local opt = string.sub(a, m, m) 616 | if opt == "l" then 617 | list = true 618 | elseif opt == "s" then 619 | ctx.strip = true 620 | elseif opt == "g" then 621 | ctx.strip = false 622 | else 623 | if arg[n] == nil or m ~= #a then usage() end 624 | if opt == "e" then 625 | if n ~= 1 then usage() end 626 | arg[1] = check(loadstring(arg[1])) 627 | elseif opt == "n" then 628 | ctx.modname = checkmodname(table.remove(arg, n)) 629 | elseif opt == "t" then 630 | ctx.type = checkarg(table.remove(arg, n), map_type, "file type") 631 | elseif opt == "a" then 632 | ctx.arch = checkarg(table.remove(arg, n), map_arch, "architecture") 633 | elseif opt == "o" then 634 | ctx.os = checkarg(table.remove(arg, n), map_os, "OS name") 635 | else 636 | usage() 637 | end 638 | end 639 | end 640 | else 641 | n = n + 1 642 | end 643 | end 644 | if list then 645 | if #arg == 0 or #arg > 2 then usage() end 646 | bclist(arg[1], arg[2] or "-") 647 | else 648 | if #arg ~= 2 then usage() end 649 | bcsave(ctx, arg[1], arg[2]) 650 | end 651 | end 652 | 653 | ------------------------------------------------------------------------------ 654 | 655 | -- Public module functions. 656 | module(...) 657 | 658 | start = docmd -- Process -b command line option. 659 | 660 | -------------------------------------------------------------------------------- /proj.win32/lua/jit/dis_arm.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT ARM disassembler module. 3 | -- 4 | -- Copyright (C) 2005-2013 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- This is a helper module used by the LuaJIT machine code dumper module. 8 | -- 9 | -- It disassembles most user-mode ARMv7 instructions 10 | -- NYI: Advanced SIMD and VFP instructions. 11 | ------------------------------------------------------------------------------ 12 | 13 | local type = type 14 | local sub, byte, format = string.sub, string.byte, string.format 15 | local match, gmatch, gsub = string.match, string.gmatch, string.gsub 16 | local concat = table.concat 17 | local bit = require("bit") 18 | local band, bor, ror, tohex = bit.band, bit.bor, bit.ror, bit.tohex 19 | local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift 20 | 21 | ------------------------------------------------------------------------------ 22 | -- Opcode maps 23 | ------------------------------------------------------------------------------ 24 | 25 | local map_loadc = { 26 | shift = 8, mask = 15, 27 | [10] = { 28 | shift = 20, mask = 1, 29 | [0] = { 30 | shift = 23, mask = 3, 31 | [0] = "vmovFmDN", "vstmFNdr", 32 | _ = { 33 | shift = 21, mask = 1, 34 | [0] = "vstrFdl", 35 | { shift = 16, mask = 15, [13] = "vpushFdr", _ = "vstmdbFNdr", } 36 | }, 37 | }, 38 | { 39 | shift = 23, mask = 3, 40 | [0] = "vmovFDNm", 41 | { shift = 16, mask = 15, [13] = "vpopFdr", _ = "vldmFNdr", }, 42 | _ = { 43 | shift = 21, mask = 1, 44 | [0] = "vldrFdl", "vldmdbFNdr", 45 | }, 46 | }, 47 | }, 48 | [11] = { 49 | shift = 20, mask = 1, 50 | [0] = { 51 | shift = 23, mask = 3, 52 | [0] = "vmovGmDN", "vstmGNdr", 53 | _ = { 54 | shift = 21, mask = 1, 55 | [0] = "vstrGdl", 56 | { shift = 16, mask = 15, [13] = "vpushGdr", _ = "vstmdbGNdr", } 57 | }, 58 | }, 59 | { 60 | shift = 23, mask = 3, 61 | [0] = "vmovGDNm", 62 | { shift = 16, mask = 15, [13] = "vpopGdr", _ = "vldmGNdr", }, 63 | _ = { 64 | shift = 21, mask = 1, 65 | [0] = "vldrGdl", "vldmdbGNdr", 66 | }, 67 | }, 68 | }, 69 | _ = { 70 | shift = 0, mask = 0 -- NYI ldc, mcrr, mrrc. 71 | }, 72 | } 73 | 74 | local map_vfps = { 75 | shift = 6, mask = 0x2c001, 76 | [0] = "vmlaF.dnm", "vmlsF.dnm", 77 | [0x04000] = "vnmlsF.dnm", [0x04001] = "vnmlaF.dnm", 78 | [0x08000] = "vmulF.dnm", [0x08001] = "vnmulF.dnm", 79 | [0x0c000] = "vaddF.dnm", [0x0c001] = "vsubF.dnm", 80 | [0x20000] = "vdivF.dnm", 81 | [0x24000] = "vfnmsF.dnm", [0x24001] = "vfnmaF.dnm", 82 | [0x28000] = "vfmaF.dnm", [0x28001] = "vfmsF.dnm", 83 | [0x2c000] = "vmovF.dY", 84 | [0x2c001] = { 85 | shift = 7, mask = 0x1e01, 86 | [0] = "vmovF.dm", "vabsF.dm", 87 | [0x0200] = "vnegF.dm", [0x0201] = "vsqrtF.dm", 88 | [0x0800] = "vcmpF.dm", [0x0801] = "vcmpeF.dm", 89 | [0x0a00] = "vcmpzF.d", [0x0a01] = "vcmpzeF.d", 90 | [0x0e01] = "vcvtG.dF.m", 91 | [0x1000] = "vcvt.f32.u32Fdm", [0x1001] = "vcvt.f32.s32Fdm", 92 | [0x1800] = "vcvtr.u32F.dm", [0x1801] = "vcvt.u32F.dm", 93 | [0x1a00] = "vcvtr.s32F.dm", [0x1a01] = "vcvt.s32F.dm", 94 | }, 95 | } 96 | 97 | local map_vfpd = { 98 | shift = 6, mask = 0x2c001, 99 | [0] = "vmlaG.dnm", "vmlsG.dnm", 100 | [0x04000] = "vnmlsG.dnm", [0x04001] = "vnmlaG.dnm", 101 | [0x08000] = "vmulG.dnm", [0x08001] = "vnmulG.dnm", 102 | [0x0c000] = "vaddG.dnm", [0x0c001] = "vsubG.dnm", 103 | [0x20000] = "vdivG.dnm", 104 | [0x24000] = "vfnmsG.dnm", [0x24001] = "vfnmaG.dnm", 105 | [0x28000] = "vfmaG.dnm", [0x28001] = "vfmsG.dnm", 106 | [0x2c000] = "vmovG.dY", 107 | [0x2c001] = { 108 | shift = 7, mask = 0x1e01, 109 | [0] = "vmovG.dm", "vabsG.dm", 110 | [0x0200] = "vnegG.dm", [0x0201] = "vsqrtG.dm", 111 | [0x0800] = "vcmpG.dm", [0x0801] = "vcmpeG.dm", 112 | [0x0a00] = "vcmpzG.d", [0x0a01] = "vcmpzeG.d", 113 | [0x0e01] = "vcvtF.dG.m", 114 | [0x1000] = "vcvt.f64.u32GdFm", [0x1001] = "vcvt.f64.s32GdFm", 115 | [0x1800] = "vcvtr.u32FdG.m", [0x1801] = "vcvt.u32FdG.m", 116 | [0x1a00] = "vcvtr.s32FdG.m", [0x1a01] = "vcvt.s32FdG.m", 117 | }, 118 | } 119 | 120 | local map_datac = { 121 | shift = 24, mask = 1, 122 | [0] = { 123 | shift = 4, mask = 1, 124 | [0] = { 125 | shift = 8, mask = 15, 126 | [10] = map_vfps, 127 | [11] = map_vfpd, 128 | -- NYI cdp, mcr, mrc. 129 | }, 130 | { 131 | shift = 8, mask = 15, 132 | [10] = { 133 | shift = 20, mask = 15, 134 | [0] = "vmovFnD", "vmovFDn", 135 | [14] = "vmsrD", 136 | [15] = { shift = 12, mask = 15, [15] = "vmrs", _ = "vmrsD", }, 137 | }, 138 | }, 139 | }, 140 | "svcT", 141 | } 142 | 143 | local map_loadcu = { 144 | shift = 0, mask = 0, -- NYI unconditional CP load/store. 145 | } 146 | 147 | local map_datacu = { 148 | shift = 0, mask = 0, -- NYI unconditional CP data. 149 | } 150 | 151 | local map_simddata = { 152 | shift = 0, mask = 0, -- NYI SIMD data. 153 | } 154 | 155 | local map_simdload = { 156 | shift = 0, mask = 0, -- NYI SIMD load/store, preload. 157 | } 158 | 159 | local map_preload = { 160 | shift = 0, mask = 0, -- NYI preload. 161 | } 162 | 163 | local map_media = { 164 | shift = 20, mask = 31, 165 | [0] = false, 166 | { --01 167 | shift = 5, mask = 7, 168 | [0] = "sadd16DNM", "sasxDNM", "ssaxDNM", "ssub16DNM", 169 | "sadd8DNM", false, false, "ssub8DNM", 170 | }, 171 | { --02 172 | shift = 5, mask = 7, 173 | [0] = "qadd16DNM", "qasxDNM", "qsaxDNM", "qsub16DNM", 174 | "qadd8DNM", false, false, "qsub8DNM", 175 | }, 176 | { --03 177 | shift = 5, mask = 7, 178 | [0] = "shadd16DNM", "shasxDNM", "shsaxDNM", "shsub16DNM", 179 | "shadd8DNM", false, false, "shsub8DNM", 180 | }, 181 | false, 182 | { --05 183 | shift = 5, mask = 7, 184 | [0] = "uadd16DNM", "uasxDNM", "usaxDNM", "usub16DNM", 185 | "uadd8DNM", false, false, "usub8DNM", 186 | }, 187 | { --06 188 | shift = 5, mask = 7, 189 | [0] = "uqadd16DNM", "uqasxDNM", "uqsaxDNM", "uqsub16DNM", 190 | "uqadd8DNM", false, false, "uqsub8DNM", 191 | }, 192 | { --07 193 | shift = 5, mask = 7, 194 | [0] = "uhadd16DNM", "uhasxDNM", "uhsaxDNM", "uhsub16DNM", 195 | "uhadd8DNM", false, false, "uhsub8DNM", 196 | }, 197 | { --08 198 | shift = 5, mask = 7, 199 | [0] = "pkhbtDNMU", false, "pkhtbDNMU", 200 | { shift = 16, mask = 15, [15] = "sxtb16DMU", _ = "sxtab16DNMU", }, 201 | "pkhbtDNMU", "selDNM", "pkhtbDNMU", 202 | }, 203 | false, 204 | { --0a 205 | shift = 5, mask = 7, 206 | [0] = "ssatDxMu", "ssat16DxM", "ssatDxMu", 207 | { shift = 16, mask = 15, [15] = "sxtbDMU", _ = "sxtabDNMU", }, 208 | "ssatDxMu", false, "ssatDxMu", 209 | }, 210 | { --0b 211 | shift = 5, mask = 7, 212 | [0] = "ssatDxMu", "revDM", "ssatDxMu", 213 | { shift = 16, mask = 15, [15] = "sxthDMU", _ = "sxtahDNMU", }, 214 | "ssatDxMu", "rev16DM", "ssatDxMu", 215 | }, 216 | { --0c 217 | shift = 5, mask = 7, 218 | [3] = { shift = 16, mask = 15, [15] = "uxtb16DMU", _ = "uxtab16DNMU", }, 219 | }, 220 | false, 221 | { --0e 222 | shift = 5, mask = 7, 223 | [0] = "usatDwMu", "usat16DwM", "usatDwMu", 224 | { shift = 16, mask = 15, [15] = "uxtbDMU", _ = "uxtabDNMU", }, 225 | "usatDwMu", false, "usatDwMu", 226 | }, 227 | { --0f 228 | shift = 5, mask = 7, 229 | [0] = "usatDwMu", "rbitDM", "usatDwMu", 230 | { shift = 16, mask = 15, [15] = "uxthDMU", _ = "uxtahDNMU", }, 231 | "usatDwMu", "revshDM", "usatDwMu", 232 | }, 233 | { --10 234 | shift = 12, mask = 15, 235 | [15] = { 236 | shift = 5, mask = 7, 237 | "smuadNMS", "smuadxNMS", "smusdNMS", "smusdxNMS", 238 | }, 239 | _ = { 240 | shift = 5, mask = 7, 241 | [0] = "smladNMSD", "smladxNMSD", "smlsdNMSD", "smlsdxNMSD", 242 | }, 243 | }, 244 | false, false, false, 245 | { --14 246 | shift = 5, mask = 7, 247 | [0] = "smlaldDNMS", "smlaldxDNMS", "smlsldDNMS", "smlsldxDNMS", 248 | }, 249 | { --15 250 | shift = 5, mask = 7, 251 | [0] = { shift = 12, mask = 15, [15] = "smmulNMS", _ = "smmlaNMSD", }, 252 | { shift = 12, mask = 15, [15] = "smmulrNMS", _ = "smmlarNMSD", }, 253 | false, false, false, false, 254 | "smmlsNMSD", "smmlsrNMSD", 255 | }, 256 | false, false, 257 | { --18 258 | shift = 5, mask = 7, 259 | [0] = { shift = 12, mask = 15, [15] = "usad8NMS", _ = "usada8NMSD", }, 260 | }, 261 | false, 262 | { --1a 263 | shift = 5, mask = 3, [2] = "sbfxDMvw", 264 | }, 265 | { --1b 266 | shift = 5, mask = 3, [2] = "sbfxDMvw", 267 | }, 268 | { --1c 269 | shift = 5, mask = 3, 270 | [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", }, 271 | }, 272 | { --1d 273 | shift = 5, mask = 3, 274 | [0] = { shift = 0, mask = 15, [15] = "bfcDvX", _ = "bfiDMvX", }, 275 | }, 276 | { --1e 277 | shift = 5, mask = 3, [2] = "ubfxDMvw", 278 | }, 279 | { --1f 280 | shift = 5, mask = 3, [2] = "ubfxDMvw", 281 | }, 282 | } 283 | 284 | local map_load = { 285 | shift = 21, mask = 9, 286 | { 287 | shift = 20, mask = 5, 288 | [0] = "strtDL", "ldrtDL", [4] = "strbtDL", [5] = "ldrbtDL", 289 | }, 290 | _ = { 291 | shift = 20, mask = 5, 292 | [0] = "strDL", "ldrDL", [4] = "strbDL", [5] = "ldrbDL", 293 | } 294 | } 295 | 296 | local map_load1 = { 297 | shift = 4, mask = 1, 298 | [0] = map_load, map_media, 299 | } 300 | 301 | local map_loadm = { 302 | shift = 20, mask = 1, 303 | [0] = { 304 | shift = 23, mask = 3, 305 | [0] = "stmdaNR", "stmNR", 306 | { shift = 16, mask = 63, [45] = "pushR", _ = "stmdbNR", }, "stmibNR", 307 | }, 308 | { 309 | shift = 23, mask = 3, 310 | [0] = "ldmdaNR", { shift = 16, mask = 63, [61] = "popR", _ = "ldmNR", }, 311 | "ldmdbNR", "ldmibNR", 312 | }, 313 | } 314 | 315 | local map_data = { 316 | shift = 21, mask = 15, 317 | [0] = "andDNPs", "eorDNPs", "subDNPs", "rsbDNPs", 318 | "addDNPs", "adcDNPs", "sbcDNPs", "rscDNPs", 319 | "tstNP", "teqNP", "cmpNP", "cmnNP", 320 | "orrDNPs", "movDPs", "bicDNPs", "mvnDPs", 321 | } 322 | 323 | local map_mul = { 324 | shift = 21, mask = 7, 325 | [0] = "mulNMSs", "mlaNMSDs", "umaalDNMS", "mlsDNMS", 326 | "umullDNMSs", "umlalDNMSs", "smullDNMSs", "smlalDNMSs", 327 | } 328 | 329 | local map_sync = { 330 | shift = 20, mask = 15, -- NYI: brackets around N. R(D+1) for ldrexd/strexd. 331 | [0] = "swpDMN", false, false, false, 332 | "swpbDMN", false, false, false, 333 | "strexDMN", "ldrexDN", "strexdDN", "ldrexdDN", 334 | "strexbDMN", "ldrexbDN", "strexhDN", "ldrexhDN", 335 | } 336 | 337 | local map_mulh = { 338 | shift = 21, mask = 3, 339 | [0] = { shift = 5, mask = 3, 340 | [0] = "smlabbNMSD", "smlatbNMSD", "smlabtNMSD", "smlattNMSD", }, 341 | { shift = 5, mask = 3, 342 | [0] = "smlawbNMSD", "smulwbNMS", "smlawtNMSD", "smulwtNMS", }, 343 | { shift = 5, mask = 3, 344 | [0] = "smlalbbDNMS", "smlaltbDNMS", "smlalbtDNMS", "smlalttDNMS", }, 345 | { shift = 5, mask = 3, 346 | [0] = "smulbbNMS", "smultbNMS", "smulbtNMS", "smulttNMS", }, 347 | } 348 | 349 | local map_misc = { 350 | shift = 4, mask = 7, 351 | -- NYI: decode PSR bits of msr. 352 | [0] = { shift = 21, mask = 1, [0] = "mrsD", "msrM", }, 353 | { shift = 21, mask = 3, "bxM", false, "clzDM", }, 354 | { shift = 21, mask = 3, "bxjM", }, 355 | { shift = 21, mask = 3, "blxM", }, 356 | false, 357 | { shift = 21, mask = 3, [0] = "qaddDMN", "qsubDMN", "qdaddDMN", "qdsubDMN", }, 358 | false, 359 | { shift = 21, mask = 3, "bkptK", }, 360 | } 361 | 362 | local map_datar = { 363 | shift = 4, mask = 9, 364 | [9] = { 365 | shift = 5, mask = 3, 366 | [0] = { shift = 24, mask = 1, [0] = map_mul, map_sync, }, 367 | { shift = 20, mask = 1, [0] = "strhDL", "ldrhDL", }, 368 | { shift = 20, mask = 1, [0] = "ldrdDL", "ldrsbDL", }, 369 | { shift = 20, mask = 1, [0] = "strdDL", "ldrshDL", }, 370 | }, 371 | _ = { 372 | shift = 20, mask = 25, 373 | [16] = { shift = 7, mask = 1, [0] = map_misc, map_mulh, }, 374 | _ = { 375 | shift = 0, mask = 0xffffffff, 376 | [bor(0xe1a00000)] = "nop", 377 | _ = map_data, 378 | } 379 | }, 380 | } 381 | 382 | local map_datai = { 383 | shift = 20, mask = 31, -- NYI: decode PSR bits of msr. Decode imm12. 384 | [16] = "movwDW", [20] = "movtDW", 385 | [18] = { shift = 0, mask = 0xf00ff, [0] = "nopv6", _ = "msrNW", }, 386 | [22] = "msrNW", 387 | _ = map_data, 388 | } 389 | 390 | local map_branch = { 391 | shift = 24, mask = 1, 392 | [0] = "bB", "blB" 393 | } 394 | 395 | local map_condins = { 396 | [0] = map_datar, map_datai, map_load, map_load1, 397 | map_loadm, map_branch, map_loadc, map_datac 398 | } 399 | 400 | -- NYI: setend. 401 | local map_uncondins = { 402 | [0] = false, map_simddata, map_simdload, map_preload, 403 | false, "blxB", map_loadcu, map_datacu, 404 | } 405 | 406 | ------------------------------------------------------------------------------ 407 | 408 | local map_gpr = { 409 | [0] = "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", 410 | "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", 411 | } 412 | 413 | local map_cond = { 414 | [0] = "eq", "ne", "hs", "lo", "mi", "pl", "vs", "vc", 415 | "hi", "ls", "ge", "lt", "gt", "le", "al", 416 | } 417 | 418 | local map_shift = { [0] = "lsl", "lsr", "asr", "ror", } 419 | 420 | ------------------------------------------------------------------------------ 421 | 422 | -- Output a nicely formatted line with an opcode and operands. 423 | local function putop(ctx, text, operands) 424 | local pos = ctx.pos 425 | local extra = "" 426 | if ctx.rel then 427 | local sym = ctx.symtab[ctx.rel] 428 | if sym then 429 | extra = "\t->"..sym 430 | elseif band(ctx.op, 0x0e000000) ~= 0x0a000000 then 431 | extra = "\t; 0x"..tohex(ctx.rel) 432 | end 433 | end 434 | if ctx.hexdump > 0 then 435 | ctx.out(format("%08x %s %-5s %s%s\n", 436 | ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) 437 | else 438 | ctx.out(format("%08x %-5s %s%s\n", 439 | ctx.addr+pos, text, concat(operands, ", "), extra)) 440 | end 441 | ctx.pos = pos + 4 442 | end 443 | 444 | -- Fallback for unknown opcodes. 445 | local function unknown(ctx) 446 | return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) 447 | end 448 | 449 | -- Format operand 2 of load/store opcodes. 450 | local function fmtload(ctx, op, pos) 451 | local base = map_gpr[band(rshift(op, 16), 15)] 452 | local x, ofs 453 | local ext = (band(op, 0x04000000) == 0) 454 | if not ext and band(op, 0x02000000) == 0 then 455 | ofs = band(op, 4095) 456 | if band(op, 0x00800000) == 0 then ofs = -ofs end 457 | if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end 458 | ofs = "#"..ofs 459 | elseif ext and band(op, 0x00400000) ~= 0 then 460 | ofs = band(op, 15) + band(rshift(op, 4), 0xf0) 461 | if band(op, 0x00800000) == 0 then ofs = -ofs end 462 | if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end 463 | ofs = "#"..ofs 464 | else 465 | ofs = map_gpr[band(op, 15)] 466 | if ext or band(op, 0xfe0) == 0 then 467 | elseif band(op, 0xfe0) == 0x60 then 468 | ofs = format("%s, rrx", ofs) 469 | else 470 | local sh = band(rshift(op, 7), 31) 471 | if sh == 0 then sh = 32 end 472 | ofs = format("%s, %s #%d", ofs, map_shift[band(rshift(op, 5), 3)], sh) 473 | end 474 | if band(op, 0x00800000) == 0 then ofs = "-"..ofs end 475 | end 476 | if ofs == "#0" then 477 | x = format("[%s]", base) 478 | elseif band(op, 0x01000000) == 0 then 479 | x = format("[%s], %s", base, ofs) 480 | else 481 | x = format("[%s, %s]", base, ofs) 482 | end 483 | if band(op, 0x01200000) == 0x01200000 then x = x.."!" end 484 | return x 485 | end 486 | 487 | -- Format operand 2 of vector load/store opcodes. 488 | local function fmtvload(ctx, op, pos) 489 | local base = map_gpr[band(rshift(op, 16), 15)] 490 | local ofs = band(op, 255)*4 491 | if band(op, 0x00800000) == 0 then ofs = -ofs end 492 | if base == "pc" then ctx.rel = ctx.addr + pos + 8 + ofs end 493 | if ofs == 0 then 494 | return format("[%s]", base) 495 | else 496 | return format("[%s, #%d]", base, ofs) 497 | end 498 | end 499 | 500 | local function fmtvr(op, vr, sh0, sh1) 501 | if vr == "s" then 502 | return format("s%d", 2*band(rshift(op, sh0), 15)+band(rshift(op, sh1), 1)) 503 | else 504 | return format("d%d", band(rshift(op, sh0), 15)+band(rshift(op, sh1-4), 16)) 505 | end 506 | end 507 | 508 | -- Disassemble a single instruction. 509 | local function disass_ins(ctx) 510 | local pos = ctx.pos 511 | local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) 512 | local op = bor(lshift(b3, 24), lshift(b2, 16), lshift(b1, 8), b0) 513 | local operands = {} 514 | local suffix = "" 515 | local last, name, pat 516 | local vr 517 | ctx.op = op 518 | ctx.rel = nil 519 | 520 | local cond = rshift(op, 28) 521 | local opat 522 | if cond == 15 then 523 | opat = map_uncondins[band(rshift(op, 25), 7)] 524 | else 525 | if cond ~= 14 then suffix = map_cond[cond] end 526 | opat = map_condins[band(rshift(op, 25), 7)] 527 | end 528 | while type(opat) ~= "string" do 529 | if not opat then return unknown(ctx) end 530 | opat = opat[band(rshift(op, opat.shift), opat.mask)] or opat._ 531 | end 532 | name, pat = match(opat, "^([a-z0-9]*)(.*)") 533 | if sub(pat, 1, 1) == "." then 534 | local s2, p2 = match(pat, "^([a-z0-9.]*)(.*)") 535 | suffix = suffix..s2 536 | pat = p2 537 | end 538 | 539 | for p in gmatch(pat, ".") do 540 | local x = nil 541 | if p == "D" then 542 | x = map_gpr[band(rshift(op, 12), 15)] 543 | elseif p == "N" then 544 | x = map_gpr[band(rshift(op, 16), 15)] 545 | elseif p == "S" then 546 | x = map_gpr[band(rshift(op, 8), 15)] 547 | elseif p == "M" then 548 | x = map_gpr[band(op, 15)] 549 | elseif p == "d" then 550 | x = fmtvr(op, vr, 12, 22) 551 | elseif p == "n" then 552 | x = fmtvr(op, vr, 16, 7) 553 | elseif p == "m" then 554 | x = fmtvr(op, vr, 0, 5) 555 | elseif p == "P" then 556 | if band(op, 0x02000000) ~= 0 then 557 | x = ror(band(op, 255), 2*band(rshift(op, 8), 15)) 558 | else 559 | x = map_gpr[band(op, 15)] 560 | if band(op, 0xff0) ~= 0 then 561 | operands[#operands+1] = x 562 | local s = map_shift[band(rshift(op, 5), 3)] 563 | local r = nil 564 | if band(op, 0xf90) == 0 then 565 | if s == "ror" then s = "rrx" else r = "#32" end 566 | elseif band(op, 0x10) == 0 then 567 | r = "#"..band(rshift(op, 7), 31) 568 | else 569 | r = map_gpr[band(rshift(op, 8), 15)] 570 | end 571 | if name == "mov" then name = s; x = r 572 | elseif r then x = format("%s %s", s, r) 573 | else x = s end 574 | end 575 | end 576 | elseif p == "L" then 577 | x = fmtload(ctx, op, pos) 578 | elseif p == "l" then 579 | x = fmtvload(ctx, op, pos) 580 | elseif p == "B" then 581 | local addr = ctx.addr + pos + 8 + arshift(lshift(op, 8), 6) 582 | if cond == 15 then addr = addr + band(rshift(op, 23), 2) end 583 | ctx.rel = addr 584 | x = "0x"..tohex(addr) 585 | elseif p == "F" then 586 | vr = "s" 587 | elseif p == "G" then 588 | vr = "d" 589 | elseif p == "." then 590 | suffix = suffix..(vr == "s" and ".f32" or ".f64") 591 | elseif p == "R" then 592 | if band(op, 0x00200000) ~= 0 and #operands == 1 then 593 | operands[1] = operands[1].."!" 594 | end 595 | local t = {} 596 | for i=0,15 do 597 | if band(rshift(op, i), 1) == 1 then t[#t+1] = map_gpr[i] end 598 | end 599 | x = "{"..concat(t, ", ").."}" 600 | elseif p == "r" then 601 | if band(op, 0x00200000) ~= 0 and #operands == 2 then 602 | operands[1] = operands[1].."!" 603 | end 604 | local s = tonumber(sub(last, 2)) 605 | local n = band(op, 255) 606 | if vr == "d" then n = rshift(n, 1) end 607 | operands[#operands] = format("{%s-%s%d}", last, vr, s+n-1) 608 | elseif p == "W" then 609 | x = band(op, 0x0fff) + band(rshift(op, 4), 0xf000) 610 | elseif p == "T" then 611 | x = "#0x"..tohex(band(op, 0x00ffffff), 6) 612 | elseif p == "U" then 613 | x = band(rshift(op, 7), 31) 614 | if x == 0 then x = nil end 615 | elseif p == "u" then 616 | x = band(rshift(op, 7), 31) 617 | if band(op, 0x40) == 0 then 618 | if x == 0 then x = nil else x = "lsl #"..x end 619 | else 620 | if x == 0 then x = "asr #32" else x = "asr #"..x end 621 | end 622 | elseif p == "v" then 623 | x = band(rshift(op, 7), 31) 624 | elseif p == "w" then 625 | x = band(rshift(op, 16), 31) 626 | elseif p == "x" then 627 | x = band(rshift(op, 16), 31) + 1 628 | elseif p == "X" then 629 | x = band(rshift(op, 16), 31) - last + 1 630 | elseif p == "Y" then 631 | x = band(rshift(op, 12), 0xf0) + band(op, 0x0f) 632 | elseif p == "K" then 633 | x = "#0x"..tohex(band(rshift(op, 4), 0x0000fff0) + band(op, 15), 4) 634 | elseif p == "s" then 635 | if band(op, 0x00100000) ~= 0 then suffix = "s"..suffix end 636 | else 637 | assert(false) 638 | end 639 | if x then 640 | last = x 641 | if type(x) == "number" then x = "#"..x end 642 | operands[#operands+1] = x 643 | end 644 | end 645 | 646 | return putop(ctx, name..suffix, operands) 647 | end 648 | 649 | ------------------------------------------------------------------------------ 650 | 651 | -- Disassemble a block of code. 652 | local function disass_block(ctx, ofs, len) 653 | if not ofs then ofs = 0 end 654 | local stop = len and ofs+len or #ctx.code 655 | ctx.pos = ofs 656 | ctx.rel = nil 657 | while ctx.pos < stop do disass_ins(ctx) end 658 | end 659 | 660 | -- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). 661 | local function create_(code, addr, out) 662 | local ctx = {} 663 | ctx.code = code 664 | ctx.addr = addr or 0 665 | ctx.out = out or io.write 666 | ctx.symtab = {} 667 | ctx.disass = disass_block 668 | ctx.hexdump = 8 669 | return ctx 670 | end 671 | 672 | -- Simple API: disassemble code (a string) at address and output via out. 673 | local function disass_(code, addr, out) 674 | create_(code, addr, out):disass() 675 | end 676 | 677 | -- Return register name for RID. 678 | local function regname_(r) 679 | if r < 16 then return map_gpr[r] end 680 | return "d"..(r-16) 681 | end 682 | 683 | -- Public module functions. 684 | module(...) 685 | 686 | create = create_ 687 | disass = disass_ 688 | regname = regname_ 689 | 690 | -------------------------------------------------------------------------------- /proj.win32/lua/jit/dump.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT compiler dump module. 3 | -- 4 | -- Copyright (C) 2005-2013 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- 8 | -- This module can be used to debug the JIT compiler itself. It dumps the 9 | -- code representations and structures used in various compiler stages. 10 | -- 11 | -- Example usage: 12 | -- 13 | -- luajit -jdump -e "local x=0; for i=1,1e6 do x=x+i end; print(x)" 14 | -- luajit -jdump=im -e "for i=1,1000 do for j=1,1000 do end end" | less -R 15 | -- luajit -jdump=is myapp.lua | less -R 16 | -- luajit -jdump=-b myapp.lua 17 | -- luajit -jdump=+aH,myapp.html myapp.lua 18 | -- luajit -jdump=ixT,myapp.dump myapp.lua 19 | -- 20 | -- The first argument specifies the dump mode. The second argument gives 21 | -- the output file name. Default output is to stdout, unless the environment 22 | -- variable LUAJIT_DUMPFILE is set. The file is overwritten every time the 23 | -- module is started. 24 | -- 25 | -- Different features can be turned on or off with the dump mode. If the 26 | -- mode starts with a '+', the following features are added to the default 27 | -- set of features; a '-' removes them. Otherwise the features are replaced. 28 | -- 29 | -- The following dump features are available (* marks the default): 30 | -- 31 | -- * t Print a line for each started, ended or aborted trace (see also -jv). 32 | -- * b Dump the traced bytecode. 33 | -- * i Dump the IR (intermediate representation). 34 | -- r Augment the IR with register/stack slots. 35 | -- s Dump the snapshot map. 36 | -- * m Dump the generated machine code. 37 | -- x Print each taken trace exit. 38 | -- X Print each taken trace exit and the contents of all registers. 39 | -- 40 | -- The output format can be set with the following characters: 41 | -- 42 | -- T Plain text output. 43 | -- A ANSI-colored text output 44 | -- H Colorized HTML + CSS output. 45 | -- 46 | -- The default output format is plain text. It's set to ANSI-colored text 47 | -- if the COLORTERM variable is set. Note: this is independent of any output 48 | -- redirection, which is actually considered a feature. 49 | -- 50 | -- You probably want to use less -R to enjoy viewing ANSI-colored text from 51 | -- a pipe or a file. Add this to your ~/.bashrc: export LESS="-R" 52 | -- 53 | ------------------------------------------------------------------------------ 54 | 55 | -- Cache some library functions and objects. 56 | local jit = require("jit") 57 | assert(jit.version_num == 20001, "LuaJIT core/library version mismatch") 58 | local jutil = require("jit.util") 59 | local vmdef = require("jit.vmdef") 60 | local funcinfo, funcbc = jutil.funcinfo, jutil.funcbc 61 | local traceinfo, traceir, tracek = jutil.traceinfo, jutil.traceir, jutil.tracek 62 | local tracemc, tracesnap = jutil.tracemc, jutil.tracesnap 63 | local traceexitstub, ircalladdr = jutil.traceexitstub, jutil.ircalladdr 64 | local bit = require("bit") 65 | local band, shl, shr = bit.band, bit.lshift, bit.rshift 66 | local sub, gsub, format = string.sub, string.gsub, string.format 67 | local byte, char, rep = string.byte, string.char, string.rep 68 | local type, tostring = type, tostring 69 | local stdout, stderr = io.stdout, io.stderr 70 | 71 | -- Load other modules on-demand. 72 | local bcline, disass 73 | 74 | -- Active flag, output file handle and dump mode. 75 | local active, out, dumpmode 76 | 77 | ------------------------------------------------------------------------------ 78 | 79 | local symtabmt = { __index = false } 80 | local symtab = {} 81 | local nexitsym = 0 82 | 83 | -- Fill nested symbol table with per-trace exit stub addresses. 84 | local function fillsymtab_tr(tr, nexit) 85 | local t = {} 86 | symtabmt.__index = t 87 | if jit.arch == "mips" or jit.arch == "mipsel" then 88 | t[traceexitstub(tr, 0)] = "exit" 89 | return 90 | end 91 | for i=0,nexit-1 do 92 | local addr = traceexitstub(tr, i) 93 | t[addr] = tostring(i) 94 | end 95 | local addr = traceexitstub(tr, nexit) 96 | if addr then t[addr] = "stack_check" end 97 | end 98 | 99 | -- Fill symbol table with trace exit stub addresses. 100 | local function fillsymtab(tr, nexit) 101 | local t = symtab 102 | if nexitsym == 0 then 103 | local ircall = vmdef.ircall 104 | for i=0,#ircall do 105 | local addr = ircalladdr(i) 106 | if addr ~= 0 then t[addr] = ircall[i] end 107 | end 108 | end 109 | if nexitsym == 1000000 then -- Per-trace exit stubs. 110 | fillsymtab_tr(tr, nexit) 111 | elseif nexit > nexitsym then -- Shared exit stubs. 112 | for i=nexitsym,nexit-1 do 113 | local addr = traceexitstub(i) 114 | if addr == nil then -- Fall back to per-trace exit stubs. 115 | fillsymtab_tr(tr, nexit) 116 | setmetatable(symtab, symtabmt) 117 | nexit = 1000000 118 | break 119 | end 120 | t[addr] = tostring(i) 121 | end 122 | nexitsym = nexit 123 | end 124 | return t 125 | end 126 | 127 | local function dumpwrite(s) 128 | out:write(s) 129 | end 130 | 131 | -- Disassemble machine code. 132 | local function dump_mcode(tr) 133 | local info = traceinfo(tr) 134 | if not info then return end 135 | local mcode, addr, loop = tracemc(tr) 136 | if not mcode then return end 137 | if not disass then disass = require("jit.dis_"..jit.arch) end 138 | out:write("---- TRACE ", tr, " mcode ", #mcode, "\n") 139 | local ctx = disass.create(mcode, addr, dumpwrite) 140 | ctx.hexdump = 0 141 | ctx.symtab = fillsymtab(tr, info.nexit) 142 | if loop ~= 0 then 143 | symtab[addr+loop] = "LOOP" 144 | ctx:disass(0, loop) 145 | out:write("->LOOP:\n") 146 | ctx:disass(loop, #mcode-loop) 147 | symtab[addr+loop] = nil 148 | else 149 | ctx:disass(0, #mcode) 150 | end 151 | end 152 | 153 | ------------------------------------------------------------------------------ 154 | 155 | local irtype_text = { 156 | [0] = "nil", 157 | "fal", 158 | "tru", 159 | "lud", 160 | "str", 161 | "p32", 162 | "thr", 163 | "pro", 164 | "fun", 165 | "p64", 166 | "cdt", 167 | "tab", 168 | "udt", 169 | "flt", 170 | "num", 171 | "i8 ", 172 | "u8 ", 173 | "i16", 174 | "u16", 175 | "int", 176 | "u32", 177 | "i64", 178 | "u64", 179 | "sfp", 180 | } 181 | 182 | local colortype_ansi = { 183 | [0] = "%s", 184 | "%s", 185 | "%s", 186 | "\027[36m%s\027[m", 187 | "\027[32m%s\027[m", 188 | "%s", 189 | "\027[1m%s\027[m", 190 | "%s", 191 | "\027[1m%s\027[m", 192 | "%s", 193 | "\027[33m%s\027[m", 194 | "\027[31m%s\027[m", 195 | "\027[36m%s\027[m", 196 | "\027[34m%s\027[m", 197 | "\027[34m%s\027[m", 198 | "\027[35m%s\027[m", 199 | "\027[35m%s\027[m", 200 | "\027[35m%s\027[m", 201 | "\027[35m%s\027[m", 202 | "\027[35m%s\027[m", 203 | "\027[35m%s\027[m", 204 | "\027[35m%s\027[m", 205 | "\027[35m%s\027[m", 206 | "\027[35m%s\027[m", 207 | } 208 | 209 | local function colorize_text(s, t) 210 | return s 211 | end 212 | 213 | local function colorize_ansi(s, t) 214 | return format(colortype_ansi[t], s) 215 | end 216 | 217 | local irtype_ansi = setmetatable({}, 218 | { __index = function(tab, t) 219 | local s = colorize_ansi(irtype_text[t], t); tab[t] = s; return s; end }) 220 | 221 | local html_escape = { ["<"] = "<", [">"] = ">", ["&"] = "&", } 222 | 223 | local function colorize_html(s, t) 224 | s = gsub(s, "[<>&]", html_escape) 225 | return format('%s', irtype_text[t], s) 226 | end 227 | 228 | local irtype_html = setmetatable({}, 229 | { __index = function(tab, t) 230 | local s = colorize_html(irtype_text[t], t); tab[t] = s; return s; end }) 231 | 232 | local header_html = [[ 233 | 251 | ]] 252 | 253 | local colorize, irtype 254 | 255 | -- Lookup tables to convert some literals into names. 256 | local litname = { 257 | ["SLOAD "] = setmetatable({}, { __index = function(t, mode) 258 | local s = "" 259 | if band(mode, 1) ~= 0 then s = s.."P" end 260 | if band(mode, 2) ~= 0 then s = s.."F" end 261 | if band(mode, 4) ~= 0 then s = s.."T" end 262 | if band(mode, 8) ~= 0 then s = s.."C" end 263 | if band(mode, 16) ~= 0 then s = s.."R" end 264 | if band(mode, 32) ~= 0 then s = s.."I" end 265 | t[mode] = s 266 | return s 267 | end}), 268 | ["XLOAD "] = { [0] = "", "R", "V", "RV", "U", "RU", "VU", "RVU", }, 269 | ["CONV "] = setmetatable({}, { __index = function(t, mode) 270 | local s = irtype[band(mode, 31)] 271 | s = irtype[band(shr(mode, 5), 31)].."."..s 272 | if band(mode, 0x400) ~= 0 then s = s.." trunc" 273 | elseif band(mode, 0x800) ~= 0 then s = s.." sext" end 274 | local c = shr(mode, 14) 275 | if c == 2 then s = s.." index" elseif c == 3 then s = s.." check" end 276 | t[mode] = s 277 | return s 278 | end}), 279 | ["FLOAD "] = vmdef.irfield, 280 | ["FREF "] = vmdef.irfield, 281 | ["FPMATH"] = vmdef.irfpm, 282 | } 283 | 284 | local function ctlsub(c) 285 | if c == "\n" then return "\\n" 286 | elseif c == "\r" then return "\\r" 287 | elseif c == "\t" then return "\\t" 288 | else return format("\\%03d", byte(c)) 289 | end 290 | end 291 | 292 | local function fmtfunc(func, pc) 293 | local fi = funcinfo(func, pc) 294 | if fi.loc then 295 | return fi.loc 296 | elseif fi.ffid then 297 | return vmdef.ffnames[fi.ffid] 298 | elseif fi.addr then 299 | return format("C:%x", fi.addr) 300 | else 301 | return "(?)" 302 | end 303 | end 304 | 305 | local function formatk(tr, idx) 306 | local k, t, slot = tracek(tr, idx) 307 | local tn = type(k) 308 | local s 309 | if tn == "number" then 310 | if k == 2^52+2^51 then 311 | s = "bias" 312 | else 313 | s = format("%+.14g", k) 314 | end 315 | elseif tn == "string" then 316 | s = format(#k > 20 and '"%.20s"~' or '"%s"', gsub(k, "%c", ctlsub)) 317 | elseif tn == "function" then 318 | s = fmtfunc(k) 319 | elseif tn == "table" then 320 | s = format("{%p}", k) 321 | elseif tn == "userdata" then 322 | if t == 12 then 323 | s = format("userdata:%p", k) 324 | else 325 | s = format("[%p]", k) 326 | if s == "[0x00000000]" then s = "NULL" end 327 | end 328 | elseif t == 21 then -- int64_t 329 | s = sub(tostring(k), 1, -3) 330 | if sub(s, 1, 1) ~= "-" then s = "+"..s end 331 | else 332 | s = tostring(k) -- For primitives. 333 | end 334 | s = colorize(format("%-4s", s), t) 335 | if slot then 336 | s = format("%s @%d", s, slot) 337 | end 338 | return s 339 | end 340 | 341 | local function printsnap(tr, snap) 342 | local n = 2 343 | for s=0,snap[1]-1 do 344 | local sn = snap[n] 345 | if shr(sn, 24) == s then 346 | n = n + 1 347 | local ref = band(sn, 0xffff) - 0x8000 -- REF_BIAS 348 | if ref < 0 then 349 | out:write(formatk(tr, ref)) 350 | elseif band(sn, 0x80000) ~= 0 then -- SNAP_SOFTFPNUM 351 | out:write(colorize(format("%04d/%04d", ref, ref+1), 14)) 352 | else 353 | local m, ot, op1, op2 = traceir(tr, ref) 354 | out:write(colorize(format("%04d", ref), band(ot, 31))) 355 | end 356 | out:write(band(sn, 0x10000) == 0 and " " or "|") -- SNAP_FRAME 357 | else 358 | out:write("---- ") 359 | end 360 | end 361 | out:write("]\n") 362 | end 363 | 364 | -- Dump snapshots (not interleaved with IR). 365 | local function dump_snap(tr) 366 | out:write("---- TRACE ", tr, " snapshots\n") 367 | for i=0,1000000000 do 368 | local snap = tracesnap(tr, i) 369 | if not snap then break end 370 | out:write(format("#%-3d %04d [ ", i, snap[0])) 371 | printsnap(tr, snap) 372 | end 373 | end 374 | 375 | -- Return a register name or stack slot for a rid/sp location. 376 | local function ridsp_name(ridsp, ins) 377 | if not disass then disass = require("jit.dis_"..jit.arch) end 378 | local rid, slot = band(ridsp, 0xff), shr(ridsp, 8) 379 | if rid == 253 or rid == 254 then 380 | return (slot == 0 or slot == 255) and " {sink" or format(" {%04d", ins-slot) 381 | end 382 | if ridsp > 255 then return format("[%x]", slot*4) end 383 | if rid < 128 then return disass.regname(rid) end 384 | return "" 385 | end 386 | 387 | -- Dump CALL* function ref and return optional ctype. 388 | local function dumpcallfunc(tr, ins) 389 | local ctype 390 | if ins > 0 then 391 | local m, ot, op1, op2 = traceir(tr, ins) 392 | if band(ot, 31) == 0 then -- nil type means CARG(func, ctype). 393 | ins = op1 394 | ctype = formatk(tr, op2) 395 | end 396 | end 397 | if ins < 0 then 398 | out:write(format("[0x%x](", tonumber((tracek(tr, ins))))) 399 | else 400 | out:write(format("%04d (", ins)) 401 | end 402 | return ctype 403 | end 404 | 405 | -- Recursively gather CALL* args and dump them. 406 | local function dumpcallargs(tr, ins) 407 | if ins < 0 then 408 | out:write(formatk(tr, ins)) 409 | else 410 | local m, ot, op1, op2 = traceir(tr, ins) 411 | local oidx = 6*shr(ot, 8) 412 | local op = sub(vmdef.irnames, oidx+1, oidx+6) 413 | if op == "CARG " then 414 | dumpcallargs(tr, op1) 415 | if op2 < 0 then 416 | out:write(" ", formatk(tr, op2)) 417 | else 418 | out:write(" ", format("%04d", op2)) 419 | end 420 | else 421 | out:write(format("%04d", ins)) 422 | end 423 | end 424 | end 425 | 426 | -- Dump IR and interleaved snapshots. 427 | local function dump_ir(tr, dumpsnap, dumpreg) 428 | local info = traceinfo(tr) 429 | if not info then return end 430 | local nins = info.nins 431 | out:write("---- TRACE ", tr, " IR\n") 432 | local irnames = vmdef.irnames 433 | local snapref = 65536 434 | local snap, snapno 435 | if dumpsnap then 436 | snap = tracesnap(tr, 0) 437 | snapref = snap[0] 438 | snapno = 0 439 | end 440 | for ins=1,nins do 441 | if ins >= snapref then 442 | if dumpreg then 443 | out:write(format(".... SNAP #%-3d [ ", snapno)) 444 | else 445 | out:write(format(".... SNAP #%-3d [ ", snapno)) 446 | end 447 | printsnap(tr, snap) 448 | snapno = snapno + 1 449 | snap = tracesnap(tr, snapno) 450 | snapref = snap and snap[0] or 65536 451 | end 452 | local m, ot, op1, op2, ridsp = traceir(tr, ins) 453 | local oidx, t = 6*shr(ot, 8), band(ot, 31) 454 | local op = sub(irnames, oidx+1, oidx+6) 455 | if op == "LOOP " then 456 | if dumpreg then 457 | out:write(format("%04d ------------ LOOP ------------\n", ins)) 458 | else 459 | out:write(format("%04d ------ LOOP ------------\n", ins)) 460 | end 461 | elseif op ~= "NOP " and op ~= "CARG " and 462 | (dumpreg or op ~= "RENAME") then 463 | local rid = band(ridsp, 255) 464 | if dumpreg then 465 | out:write(format("%04d %-6s", ins, ridsp_name(ridsp, ins))) 466 | else 467 | out:write(format("%04d ", ins)) 468 | end 469 | out:write(format("%s%s %s %s ", 470 | (rid == 254 or rid == 253) and "}" or 471 | (band(ot, 128) == 0 and " " or ">"), 472 | band(ot, 64) == 0 and " " or "+", 473 | irtype[t], op)) 474 | local m1, m2 = band(m, 3), band(m, 3*4) 475 | if sub(op, 1, 4) == "CALL" then 476 | local ctype 477 | if m2 == 1*4 then -- op2 == IRMlit 478 | out:write(format("%-10s (", vmdef.ircall[op2])) 479 | else 480 | ctype = dumpcallfunc(tr, op2) 481 | end 482 | if op1 ~= -1 then dumpcallargs(tr, op1) end 483 | out:write(")") 484 | if ctype then out:write(" ctype ", ctype) end 485 | elseif op == "CNEW " and op2 == -1 then 486 | out:write(formatk(tr, op1)) 487 | elseif m1 ~= 3 then -- op1 != IRMnone 488 | if op1 < 0 then 489 | out:write(formatk(tr, op1)) 490 | else 491 | out:write(format(m1 == 0 and "%04d" or "#%-3d", op1)) 492 | end 493 | if m2 ~= 3*4 then -- op2 != IRMnone 494 | if m2 == 1*4 then -- op2 == IRMlit 495 | local litn = litname[op] 496 | if litn and litn[op2] then 497 | out:write(" ", litn[op2]) 498 | elseif op == "UREFO " or op == "UREFC " then 499 | out:write(format(" #%-3d", shr(op2, 8))) 500 | else 501 | out:write(format(" #%-3d", op2)) 502 | end 503 | elseif op2 < 0 then 504 | out:write(" ", formatk(tr, op2)) 505 | else 506 | out:write(format(" %04d", op2)) 507 | end 508 | end 509 | end 510 | out:write("\n") 511 | end 512 | end 513 | if snap then 514 | if dumpreg then 515 | out:write(format(".... SNAP #%-3d [ ", snapno)) 516 | else 517 | out:write(format(".... SNAP #%-3d [ ", snapno)) 518 | end 519 | printsnap(tr, snap) 520 | end 521 | end 522 | 523 | ------------------------------------------------------------------------------ 524 | 525 | local recprefix = "" 526 | local recdepth = 0 527 | 528 | -- Format trace error message. 529 | local function fmterr(err, info) 530 | if type(err) == "number" then 531 | if type(info) == "function" then info = fmtfunc(info) end 532 | err = format(vmdef.traceerr[err], info) 533 | end 534 | return err 535 | end 536 | 537 | -- Dump trace states. 538 | local function dump_trace(what, tr, func, pc, otr, oex) 539 | if what == "stop" or (what == "abort" and dumpmode.a) then 540 | if dumpmode.i then dump_ir(tr, dumpmode.s, dumpmode.r and what == "stop") 541 | elseif dumpmode.s then dump_snap(tr) end 542 | if dumpmode.m then dump_mcode(tr) end 543 | end 544 | if what == "start" then 545 | if dumpmode.H then out:write('
\n') end
546 |     out:write("---- TRACE ", tr, " ", what)
547 |     if otr then out:write(" ", otr, "/", oex) end
548 |     out:write(" ", fmtfunc(func, pc), "\n")
549 |     recprefix = ""
550 |   elseif what == "stop" or what == "abort" then
551 |     out:write("---- TRACE ", tr, " ", what)
552 |     recprefix = nil
553 |     if what == "abort" then
554 |       out:write(" ", fmtfunc(func, pc), " -- ", fmterr(otr, oex), "\n")
555 |     else
556 |       local info = traceinfo(tr)
557 |       local link, ltype = info.link, info.linktype
558 |       if link == tr or link == 0 then
559 | 	out:write(" -> ", ltype, "\n")
560 |       elseif ltype == "root" then
561 | 	out:write(" -> ", link, "\n")
562 |       else
563 | 	out:write(" -> ", link, " ", ltype, "\n")
564 |       end
565 |     end
566 |     if dumpmode.H then out:write("
\n\n") else out:write("\n") end 567 | else 568 | out:write("---- TRACE ", what, "\n\n") 569 | end 570 | out:flush() 571 | end 572 | 573 | -- Dump recorded bytecode. 574 | local function dump_record(tr, func, pc, depth, callee) 575 | if depth ~= recdepth then 576 | recdepth = depth 577 | recprefix = rep(" .", depth) 578 | end 579 | local line 580 | if pc >= 0 then 581 | line = bcline(func, pc, recprefix) 582 | if dumpmode.H then line = gsub(line, "[<>&]", html_escape) end 583 | else 584 | line = "0000 "..recprefix.." FUNCC \n" 585 | callee = func 586 | end 587 | if pc <= 0 then 588 | out:write(sub(line, 1, -2), " ; ", fmtfunc(func), "\n") 589 | else 590 | out:write(line) 591 | end 592 | if pc >= 0 and band(funcbc(func, pc), 0xff) < 16 then -- ORDER BC 593 | out:write(bcline(func, pc+1, recprefix)) -- Write JMP for cond. 594 | end 595 | end 596 | 597 | ------------------------------------------------------------------------------ 598 | 599 | -- Dump taken trace exits. 600 | local function dump_texit(tr, ex, ngpr, nfpr, ...) 601 | out:write("---- TRACE ", tr, " exit ", ex, "\n") 602 | if dumpmode.X then 603 | local regs = {...} 604 | if jit.arch == "x64" then 605 | for i=1,ngpr do 606 | out:write(format(" %016x", regs[i])) 607 | if i % 4 == 0 then out:write("\n") end 608 | end 609 | else 610 | for i=1,ngpr do 611 | out:write(format(" %08x", regs[i])) 612 | if i % 8 == 0 then out:write("\n") end 613 | end 614 | end 615 | if jit.arch == "mips" or jit.arch == "mipsel" then 616 | for i=1,nfpr,2 do 617 | out:write(format(" %+17.14g", regs[ngpr+i])) 618 | if i % 8 == 7 then out:write("\n") end 619 | end 620 | else 621 | for i=1,nfpr do 622 | out:write(format(" %+17.14g", regs[ngpr+i])) 623 | if i % 4 == 0 then out:write("\n") end 624 | end 625 | end 626 | end 627 | end 628 | 629 | ------------------------------------------------------------------------------ 630 | 631 | -- Detach dump handlers. 632 | local function dumpoff() 633 | if active then 634 | active = false 635 | jit.attach(dump_texit) 636 | jit.attach(dump_record) 637 | jit.attach(dump_trace) 638 | if out and out ~= stdout and out ~= stderr then out:close() end 639 | out = nil 640 | end 641 | end 642 | 643 | -- Open the output file and attach dump handlers. 644 | local function dumpon(opt, outfile) 645 | if active then dumpoff() end 646 | 647 | local colormode = os.getenv("COLORTERM") and "A" or "T" 648 | if opt then 649 | opt = gsub(opt, "[TAH]", function(mode) colormode = mode; return ""; end) 650 | end 651 | 652 | local m = { t=true, b=true, i=true, m=true, } 653 | if opt and opt ~= "" then 654 | local o = sub(opt, 1, 1) 655 | if o ~= "+" and o ~= "-" then m = {} end 656 | for i=1,#opt do m[sub(opt, i, i)] = (o ~= "-") end 657 | end 658 | dumpmode = m 659 | 660 | if m.t or m.b or m.i or m.s or m.m then 661 | jit.attach(dump_trace, "trace") 662 | end 663 | if m.b then 664 | jit.attach(dump_record, "record") 665 | if not bcline then bcline = require("jit.bc").line end 666 | end 667 | if m.x or m.X then 668 | jit.attach(dump_texit, "texit") 669 | end 670 | 671 | if not outfile then outfile = os.getenv("LUAJIT_DUMPFILE") end 672 | if outfile then 673 | out = outfile == "-" and stdout or assert(io.open(outfile, "w")) 674 | else 675 | out = stdout 676 | end 677 | 678 | m[colormode] = true 679 | if colormode == "A" then 680 | colorize = colorize_ansi 681 | irtype = irtype_ansi 682 | elseif colormode == "H" then 683 | colorize = colorize_html 684 | irtype = irtype_html 685 | out:write(header_html) 686 | else 687 | colorize = colorize_text 688 | irtype = irtype_text 689 | end 690 | 691 | active = true 692 | end 693 | 694 | -- Public module functions. 695 | module(...) 696 | 697 | on = dumpon 698 | off = dumpoff 699 | start = dumpon -- For -j command line option. 700 | 701 | -------------------------------------------------------------------------------- /proj.win32/lua/jit/dis_ppc.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT PPC disassembler module. 3 | -- 4 | -- Copyright (C) 2005-2013 Mike Pall. All rights reserved. 5 | -- Released under the MIT/X license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- This is a helper module used by the LuaJIT machine code dumper module. 8 | -- 9 | -- It disassembles all common, non-privileged 32/64 bit PowerPC instructions 10 | -- plus the e500 SPE instructions and some Cell/Xenon extensions. 11 | -- 12 | -- NYI: VMX, VMX128 13 | ------------------------------------------------------------------------------ 14 | 15 | local type = type 16 | local sub, byte, format = string.sub, string.byte, string.format 17 | local match, gmatch, gsub = string.match, string.gmatch, string.gsub 18 | local concat = table.concat 19 | local bit = require("bit") 20 | local band, bor, tohex = bit.band, bit.bor, bit.tohex 21 | local lshift, rshift, arshift = bit.lshift, bit.rshift, bit.arshift 22 | 23 | ------------------------------------------------------------------------------ 24 | -- Primary and extended opcode maps 25 | ------------------------------------------------------------------------------ 26 | 27 | local map_crops = { 28 | shift = 1, mask = 1023, 29 | [0] = "mcrfXX", 30 | [33] = "crnor|crnotCCC=", [129] = "crandcCCC", 31 | [193] = "crxor|crclrCCC%", [225] = "crnandCCC", 32 | [257] = "crandCCC", [289] = "creqv|crsetCCC%", 33 | [417] = "crorcCCC", [449] = "cror|crmoveCCC=", 34 | [16] = "b_lrKB", [528] = "b_ctrKB", 35 | [150] = "isync", 36 | } 37 | 38 | local map_rlwinm = setmetatable({ 39 | shift = 0, mask = -1, 40 | }, 41 | { __index = function(t, x) 42 | local rot = band(rshift(x, 11), 31) 43 | local mb = band(rshift(x, 6), 31) 44 | local me = band(rshift(x, 1), 31) 45 | if mb == 0 and me == 31-rot then 46 | return "slwiRR~A." 47 | elseif me == 31 and mb == 32-rot then 48 | return "srwiRR~-A." 49 | else 50 | return "rlwinmRR~AAA." 51 | end 52 | end 53 | }) 54 | 55 | local map_rld = { 56 | shift = 2, mask = 7, 57 | [0] = "rldiclRR~HM.", "rldicrRR~HM.", "rldicRR~HM.", "rldimiRR~HM.", 58 | { 59 | shift = 1, mask = 1, 60 | [0] = "rldclRR~RM.", "rldcrRR~RM.", 61 | }, 62 | } 63 | 64 | local map_ext = setmetatable({ 65 | shift = 1, mask = 1023, 66 | 67 | [0] = "cmp_YLRR", [32] = "cmpl_YLRR", 68 | [4] = "twARR", [68] = "tdARR", 69 | 70 | [8] = "subfcRRR.", [40] = "subfRRR.", 71 | [104] = "negRR.", [136] = "subfeRRR.", 72 | [200] = "subfzeRR.", [232] = "subfmeRR.", 73 | [520] = "subfcoRRR.", [552] = "subfoRRR.", 74 | [616] = "negoRR.", [648] = "subfeoRRR.", 75 | [712] = "subfzeoRR.", [744] = "subfmeoRR.", 76 | 77 | [9] = "mulhduRRR.", [73] = "mulhdRRR.", [233] = "mulldRRR.", 78 | [457] = "divduRRR.", [489] = "divdRRR.", 79 | [745] = "mulldoRRR.", 80 | [969] = "divduoRRR.", [1001] = "divdoRRR.", 81 | 82 | [10] = "addcRRR.", [138] = "addeRRR.", 83 | [202] = "addzeRR.", [234] = "addmeRR.", [266] = "addRRR.", 84 | [522] = "addcoRRR.", [650] = "addeoRRR.", 85 | [714] = "addzeoRR.", [746] = "addmeoRR.", [778] = "addoRRR.", 86 | 87 | [11] = "mulhwuRRR.", [75] = "mulhwRRR.", [235] = "mullwRRR.", 88 | [459] = "divwuRRR.", [491] = "divwRRR.", 89 | [747] = "mullwoRRR.", 90 | [971] = "divwouRRR.", [1003] = "divwoRRR.", 91 | 92 | [15] = "iselltRRR", [47] = "iselgtRRR", [79] = "iseleqRRR", 93 | 94 | [144] = { shift = 20, mask = 1, [0] = "mtcrfRZ~", "mtocrfRZ~", }, 95 | [19] = { shift = 20, mask = 1, [0] = "mfcrR", "mfocrfRZ", }, 96 | [371] = { shift = 11, mask = 1023, [392] = "mftbR", [424] = "mftbuR", }, 97 | [339] = { 98 | shift = 11, mask = 1023, 99 | [32] = "mferR", [256] = "mflrR", [288] = "mfctrR", [16] = "mfspefscrR", 100 | }, 101 | [467] = { 102 | shift = 11, mask = 1023, 103 | [32] = "mtxerR", [256] = "mtlrR", [288] = "mtctrR", [16] = "mtspefscrR", 104 | }, 105 | 106 | [20] = "lwarxRR0R", [84] = "ldarxRR0R", 107 | 108 | [21] = "ldxRR0R", [53] = "lduxRRR", 109 | [149] = "stdxRR0R", [181] = "stduxRRR", 110 | [341] = "lwaxRR0R", [373] = "lwauxRRR", 111 | 112 | [23] = "lwzxRR0R", [55] = "lwzuxRRR", 113 | [87] = "lbzxRR0R", [119] = "lbzuxRRR", 114 | [151] = "stwxRR0R", [183] = "stwuxRRR", 115 | [215] = "stbxRR0R", [247] = "stbuxRRR", 116 | [279] = "lhzxRR0R", [311] = "lhzuxRRR", 117 | [343] = "lhaxRR0R", [375] = "lhauxRRR", 118 | [407] = "sthxRR0R", [439] = "sthuxRRR", 119 | 120 | [54] = "dcbst-R0R", [86] = "dcbf-R0R", 121 | [150] = "stwcxRR0R.", [214] = "stdcxRR0R.", 122 | [246] = "dcbtst-R0R", [278] = "dcbt-R0R", 123 | [310] = "eciwxRR0R", [438] = "ecowxRR0R", 124 | [470] = "dcbi-RR", 125 | 126 | [598] = { 127 | shift = 21, mask = 3, 128 | [0] = "sync", "lwsync", "ptesync", 129 | }, 130 | [758] = "dcba-RR", 131 | [854] = "eieio", [982] = "icbi-R0R", [1014] = "dcbz-R0R", 132 | 133 | [26] = "cntlzwRR~", [58] = "cntlzdRR~", 134 | [122] = "popcntbRR~", 135 | [154] = "prtywRR~", [186] = "prtydRR~", 136 | 137 | [28] = "andRR~R.", [60] = "andcRR~R.", [124] = "nor|notRR~R=.", 138 | [284] = "eqvRR~R.", [316] = "xorRR~R.", 139 | [412] = "orcRR~R.", [444] = "or|mrRR~R=.", [476] = "nandRR~R.", 140 | [508] = "cmpbRR~R", 141 | 142 | [512] = "mcrxrX", 143 | 144 | [532] = "ldbrxRR0R", [660] = "stdbrxRR0R", 145 | 146 | [533] = "lswxRR0R", [597] = "lswiRR0A", 147 | [661] = "stswxRR0R", [725] = "stswiRR0A", 148 | 149 | [534] = "lwbrxRR0R", [662] = "stwbrxRR0R", 150 | [790] = "lhbrxRR0R", [918] = "sthbrxRR0R", 151 | 152 | [535] = "lfsxFR0R", [567] = "lfsuxFRR", 153 | [599] = "lfdxFR0R", [631] = "lfduxFRR", 154 | [663] = "stfsxFR0R", [695] = "stfsuxFRR", 155 | [727] = "stfdxFR0R", [759] = "stfduxFR0R", 156 | [855] = "lfiwaxFR0R", 157 | [983] = "stfiwxFR0R", 158 | 159 | [24] = "slwRR~R.", 160 | 161 | [27] = "sldRR~R.", [536] = "srwRR~R.", 162 | [792] = "srawRR~R.", [824] = "srawiRR~A.", 163 | 164 | [794] = "sradRR~R.", [826] = "sradiRR~H.", [827] = "sradiRR~H.", 165 | [922] = "extshRR~.", [954] = "extsbRR~.", [986] = "extswRR~.", 166 | 167 | [539] = "srdRR~R.", 168 | }, 169 | { __index = function(t, x) 170 | if band(x, 31) == 15 then return "iselRRRC" end 171 | end 172 | }) 173 | 174 | local map_ld = { 175 | shift = 0, mask = 3, 176 | [0] = "ldRRE", "lduRRE", "lwaRRE", 177 | } 178 | 179 | local map_std = { 180 | shift = 0, mask = 3, 181 | [0] = "stdRRE", "stduRRE", 182 | } 183 | 184 | local map_fps = { 185 | shift = 5, mask = 1, 186 | { 187 | shift = 1, mask = 15, 188 | [0] = false, false, "fdivsFFF.", false, 189 | "fsubsFFF.", "faddsFFF.", "fsqrtsF-F.", false, 190 | "fresF-F.", "fmulsFF-F.", "frsqrtesF-F.", false, 191 | "fmsubsFFFF~.", "fmaddsFFFF~.", "fnmsubsFFFF~.", "fnmaddsFFFF~.", 192 | } 193 | } 194 | 195 | local map_fpd = { 196 | shift = 5, mask = 1, 197 | [0] = { 198 | shift = 1, mask = 1023, 199 | [0] = "fcmpuXFF", [32] = "fcmpoXFF", [64] = "mcrfsXX", 200 | [38] = "mtfsb1A.", [70] = "mtfsb0A.", [134] = "mtfsfiA>>-A>", 201 | [8] = "fcpsgnFFF.", [40] = "fnegF-F.", [72] = "fmrF-F.", 202 | [136] = "fnabsF-F.", [264] = "fabsF-F.", 203 | [12] = "frspF-F.", 204 | [14] = "fctiwF-F.", [15] = "fctiwzF-F.", 205 | [583] = "mffsF.", [711] = "mtfsfZF.", 206 | [392] = "frinF-F.", [424] = "frizF-F.", 207 | [456] = "fripF-F.", [488] = "frimF-F.", 208 | [814] = "fctidF-F.", [815] = "fctidzF-F.", [846] = "fcfidF-F.", 209 | }, 210 | { 211 | shift = 1, mask = 15, 212 | [0] = false, false, "fdivFFF.", false, 213 | "fsubFFF.", "faddFFF.", "fsqrtF-F.", "fselFFFF~.", 214 | "freF-F.", "fmulFF-F.", "frsqrteF-F.", false, 215 | "fmsubFFFF~.", "fmaddFFFF~.", "fnmsubFFFF~.", "fnmaddFFFF~.", 216 | } 217 | } 218 | 219 | local map_spe = { 220 | shift = 0, mask = 2047, 221 | 222 | [512] = "evaddwRRR", [514] = "evaddiwRAR~", 223 | [516] = "evsubwRRR~", [518] = "evsubiwRAR~", 224 | [520] = "evabsRR", [521] = "evnegRR", 225 | [522] = "evextsbRR", [523] = "evextshRR", [524] = "evrndwRR", 226 | [525] = "evcntlzwRR", [526] = "evcntlswRR", 227 | 228 | [527] = "brincRRR", 229 | 230 | [529] = "evandRRR", [530] = "evandcRRR", [534] = "evxorRRR", 231 | [535] = "evor|evmrRRR=", [536] = "evnor|evnotRRR=", 232 | [537] = "eveqvRRR", [539] = "evorcRRR", [542] = "evnandRRR", 233 | 234 | [544] = "evsrwuRRR", [545] = "evsrwsRRR", 235 | [546] = "evsrwiuRRA", [547] = "evsrwisRRA", 236 | [548] = "evslwRRR", [550] = "evslwiRRA", 237 | [552] = "evrlwRRR", [553] = "evsplatiRS", 238 | [554] = "evrlwiRRA", [555] = "evsplatfiRS", 239 | [556] = "evmergehiRRR", [557] = "evmergeloRRR", 240 | [558] = "evmergehiloRRR", [559] = "evmergelohiRRR", 241 | 242 | [560] = "evcmpgtuYRR", [561] = "evcmpgtsYRR", 243 | [562] = "evcmpltuYRR", [563] = "evcmpltsYRR", 244 | [564] = "evcmpeqYRR", 245 | 246 | [632] = "evselRRR", [633] = "evselRRRW", 247 | [634] = "evselRRRW", [635] = "evselRRRW", 248 | [636] = "evselRRRW", [637] = "evselRRRW", 249 | [638] = "evselRRRW", [639] = "evselRRRW", 250 | 251 | [640] = "evfsaddRRR", [641] = "evfssubRRR", 252 | [644] = "evfsabsRR", [645] = "evfsnabsRR", [646] = "evfsnegRR", 253 | [648] = "evfsmulRRR", [649] = "evfsdivRRR", 254 | [652] = "evfscmpgtYRR", [653] = "evfscmpltYRR", [654] = "evfscmpeqYRR", 255 | [656] = "evfscfuiR-R", [657] = "evfscfsiR-R", 256 | [658] = "evfscfufR-R", [659] = "evfscfsfR-R", 257 | [660] = "evfsctuiR-R", [661] = "evfsctsiR-R", 258 | [662] = "evfsctufR-R", [663] = "evfsctsfR-R", 259 | [664] = "evfsctuizR-R", [666] = "evfsctsizR-R", 260 | [668] = "evfststgtYRR", [669] = "evfststltYRR", [670] = "evfststeqYRR", 261 | 262 | [704] = "efsaddRRR", [705] = "efssubRRR", 263 | [708] = "efsabsRR", [709] = "efsnabsRR", [710] = "efsnegRR", 264 | [712] = "efsmulRRR", [713] = "efsdivRRR", 265 | [716] = "efscmpgtYRR", [717] = "efscmpltYRR", [718] = "efscmpeqYRR", 266 | [719] = "efscfdR-R", 267 | [720] = "efscfuiR-R", [721] = "efscfsiR-R", 268 | [722] = "efscfufR-R", [723] = "efscfsfR-R", 269 | [724] = "efsctuiR-R", [725] = "efsctsiR-R", 270 | [726] = "efsctufR-R", [727] = "efsctsfR-R", 271 | [728] = "efsctuizR-R", [730] = "efsctsizR-R", 272 | [732] = "efststgtYRR", [733] = "efststltYRR", [734] = "efststeqYRR", 273 | 274 | [736] = "efdaddRRR", [737] = "efdsubRRR", 275 | [738] = "efdcfuidR-R", [739] = "efdcfsidR-R", 276 | [740] = "efdabsRR", [741] = "efdnabsRR", [742] = "efdnegRR", 277 | [744] = "efdmulRRR", [745] = "efddivRRR", 278 | [746] = "efdctuidzR-R", [747] = "efdctsidzR-R", 279 | [748] = "efdcmpgtYRR", [749] = "efdcmpltYRR", [750] = "efdcmpeqYRR", 280 | [751] = "efdcfsR-R", 281 | [752] = "efdcfuiR-R", [753] = "efdcfsiR-R", 282 | [754] = "efdcfufR-R", [755] = "efdcfsfR-R", 283 | [756] = "efdctuiR-R", [757] = "efdctsiR-R", 284 | [758] = "efdctufR-R", [759] = "efdctsfR-R", 285 | [760] = "efdctuizR-R", [762] = "efdctsizR-R", 286 | [764] = "efdtstgtYRR", [765] = "efdtstltYRR", [766] = "efdtsteqYRR", 287 | 288 | [768] = "evlddxRR0R", [769] = "evlddRR8", 289 | [770] = "evldwxRR0R", [771] = "evldwRR8", 290 | [772] = "evldhxRR0R", [773] = "evldhRR8", 291 | [776] = "evlhhesplatxRR0R", [777] = "evlhhesplatRR2", 292 | [780] = "evlhhousplatxRR0R", [781] = "evlhhousplatRR2", 293 | [782] = "evlhhossplatxRR0R", [783] = "evlhhossplatRR2", 294 | [784] = "evlwhexRR0R", [785] = "evlwheRR4", 295 | [788] = "evlwhouxRR0R", [789] = "evlwhouRR4", 296 | [790] = "evlwhosxRR0R", [791] = "evlwhosRR4", 297 | [792] = "evlwwsplatxRR0R", [793] = "evlwwsplatRR4", 298 | [796] = "evlwhsplatxRR0R", [797] = "evlwhsplatRR4", 299 | 300 | [800] = "evstddxRR0R", [801] = "evstddRR8", 301 | [802] = "evstdwxRR0R", [803] = "evstdwRR8", 302 | [804] = "evstdhxRR0R", [805] = "evstdhRR8", 303 | [816] = "evstwhexRR0R", [817] = "evstwheRR4", 304 | [820] = "evstwhoxRR0R", [821] = "evstwhoRR4", 305 | [824] = "evstwwexRR0R", [825] = "evstwweRR4", 306 | [828] = "evstwwoxRR0R", [829] = "evstwwoRR4", 307 | 308 | [1027] = "evmhessfRRR", [1031] = "evmhossfRRR", [1032] = "evmheumiRRR", 309 | [1033] = "evmhesmiRRR", [1035] = "evmhesmfRRR", [1036] = "evmhoumiRRR", 310 | [1037] = "evmhosmiRRR", [1039] = "evmhosmfRRR", [1059] = "evmhessfaRRR", 311 | [1063] = "evmhossfaRRR", [1064] = "evmheumiaRRR", [1065] = "evmhesmiaRRR", 312 | [1067] = "evmhesmfaRRR", [1068] = "evmhoumiaRRR", [1069] = "evmhosmiaRRR", 313 | [1071] = "evmhosmfaRRR", [1095] = "evmwhssfRRR", [1096] = "evmwlumiRRR", 314 | [1100] = "evmwhumiRRR", [1101] = "evmwhsmiRRR", [1103] = "evmwhsmfRRR", 315 | [1107] = "evmwssfRRR", [1112] = "evmwumiRRR", [1113] = "evmwsmiRRR", 316 | [1115] = "evmwsmfRRR", [1127] = "evmwhssfaRRR", [1128] = "evmwlumiaRRR", 317 | [1132] = "evmwhumiaRRR", [1133] = "evmwhsmiaRRR", [1135] = "evmwhsmfaRRR", 318 | [1139] = "evmwssfaRRR", [1144] = "evmwumiaRRR", [1145] = "evmwsmiaRRR", 319 | [1147] = "evmwsmfaRRR", 320 | 321 | [1216] = "evaddusiaawRR", [1217] = "evaddssiaawRR", 322 | [1218] = "evsubfusiaawRR", [1219] = "evsubfssiaawRR", 323 | [1220] = "evmraRR", 324 | [1222] = "evdivwsRRR", [1223] = "evdivwuRRR", 325 | [1224] = "evaddumiaawRR", [1225] = "evaddsmiaawRR", 326 | [1226] = "evsubfumiaawRR", [1227] = "evsubfsmiaawRR", 327 | 328 | [1280] = "evmheusiaawRRR", [1281] = "evmhessiaawRRR", 329 | [1283] = "evmhessfaawRRR", [1284] = "evmhousiaawRRR", 330 | [1285] = "evmhossiaawRRR", [1287] = "evmhossfaawRRR", 331 | [1288] = "evmheumiaawRRR", [1289] = "evmhesmiaawRRR", 332 | [1291] = "evmhesmfaawRRR", [1292] = "evmhoumiaawRRR", 333 | [1293] = "evmhosmiaawRRR", [1295] = "evmhosmfaawRRR", 334 | [1320] = "evmhegumiaaRRR", [1321] = "evmhegsmiaaRRR", 335 | [1323] = "evmhegsmfaaRRR", [1324] = "evmhogumiaaRRR", 336 | [1325] = "evmhogsmiaaRRR", [1327] = "evmhogsmfaaRRR", 337 | [1344] = "evmwlusiaawRRR", [1345] = "evmwlssiaawRRR", 338 | [1352] = "evmwlumiaawRRR", [1353] = "evmwlsmiaawRRR", 339 | [1363] = "evmwssfaaRRR", [1368] = "evmwumiaaRRR", 340 | [1369] = "evmwsmiaaRRR", [1371] = "evmwsmfaaRRR", 341 | [1408] = "evmheusianwRRR", [1409] = "evmhessianwRRR", 342 | [1411] = "evmhessfanwRRR", [1412] = "evmhousianwRRR", 343 | [1413] = "evmhossianwRRR", [1415] = "evmhossfanwRRR", 344 | [1416] = "evmheumianwRRR", [1417] = "evmhesmianwRRR", 345 | [1419] = "evmhesmfanwRRR", [1420] = "evmhoumianwRRR", 346 | [1421] = "evmhosmianwRRR", [1423] = "evmhosmfanwRRR", 347 | [1448] = "evmhegumianRRR", [1449] = "evmhegsmianRRR", 348 | [1451] = "evmhegsmfanRRR", [1452] = "evmhogumianRRR", 349 | [1453] = "evmhogsmianRRR", [1455] = "evmhogsmfanRRR", 350 | [1472] = "evmwlusianwRRR", [1473] = "evmwlssianwRRR", 351 | [1480] = "evmwlumianwRRR", [1481] = "evmwlsmianwRRR", 352 | [1491] = "evmwssfanRRR", [1496] = "evmwumianRRR", 353 | [1497] = "evmwsmianRRR", [1499] = "evmwsmfanRRR", 354 | } 355 | 356 | local map_pri = { 357 | [0] = false, false, "tdiARI", "twiARI", 358 | map_spe, false, false, "mulliRRI", 359 | "subficRRI", false, "cmpl_iYLRU", "cmp_iYLRI", 360 | "addicRRI", "addic.RRI", "addi|liRR0I", "addis|lisRR0I", 361 | "b_KBJ", "sc", "bKJ", map_crops, 362 | "rlwimiRR~AAA.", map_rlwinm, false, "rlwnmRR~RAA.", 363 | "oriNRR~U", "orisRR~U", "xoriRR~U", "xorisRR~U", 364 | "andi.RR~U", "andis.RR~U", map_rld, map_ext, 365 | "lwzRRD", "lwzuRRD", "lbzRRD", "lbzuRRD", 366 | "stwRRD", "stwuRRD", "stbRRD", "stbuRRD", 367 | "lhzRRD", "lhzuRRD", "lhaRRD", "lhauRRD", 368 | "sthRRD", "sthuRRD", "lmwRRD", "stmwRRD", 369 | "lfsFRD", "lfsuFRD", "lfdFRD", "lfduFRD", 370 | "stfsFRD", "stfsuFRD", "stfdFRD", "stfduFRD", 371 | false, false, map_ld, map_fps, 372 | false, false, map_std, map_fpd, 373 | } 374 | 375 | ------------------------------------------------------------------------------ 376 | 377 | local map_gpr = { 378 | [0] = "r0", "sp", "r2", "r3", "r4", "r5", "r6", "r7", 379 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", 380 | "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", 381 | "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", 382 | } 383 | 384 | local map_cond = { [0] = "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", } 385 | 386 | -- Format a condition bit. 387 | local function condfmt(cond) 388 | if cond <= 3 then 389 | return map_cond[band(cond, 3)] 390 | else 391 | return format("4*cr%d+%s", rshift(cond, 2), map_cond[band(cond, 3)]) 392 | end 393 | end 394 | 395 | ------------------------------------------------------------------------------ 396 | 397 | -- Output a nicely formatted line with an opcode and operands. 398 | local function putop(ctx, text, operands) 399 | local pos = ctx.pos 400 | local extra = "" 401 | if ctx.rel then 402 | local sym = ctx.symtab[ctx.rel] 403 | if sym then extra = "\t->"..sym end 404 | end 405 | if ctx.hexdump > 0 then 406 | ctx.out(format("%08x %s %-7s %s%s\n", 407 | ctx.addr+pos, tohex(ctx.op), text, concat(operands, ", "), extra)) 408 | else 409 | ctx.out(format("%08x %-7s %s%s\n", 410 | ctx.addr+pos, text, concat(operands, ", "), extra)) 411 | end 412 | ctx.pos = pos + 4 413 | end 414 | 415 | -- Fallback for unknown opcodes. 416 | local function unknown(ctx) 417 | return putop(ctx, ".long", { "0x"..tohex(ctx.op) }) 418 | end 419 | 420 | -- Disassemble a single instruction. 421 | local function disass_ins(ctx) 422 | local pos = ctx.pos 423 | local b0, b1, b2, b3 = byte(ctx.code, pos+1, pos+4) 424 | local op = bor(lshift(b0, 24), lshift(b1, 16), lshift(b2, 8), b3) 425 | local operands = {} 426 | local last = nil 427 | local rs = 21 428 | ctx.op = op 429 | ctx.rel = nil 430 | 431 | local opat = map_pri[rshift(b0, 2)] 432 | while type(opat) ~= "string" do 433 | if not opat then return unknown(ctx) end 434 | opat = opat[band(rshift(op, opat.shift), opat.mask)] 435 | end 436 | local name, pat = match(opat, "^([a-z0-9_.]*)(.*)") 437 | local altname, pat2 = match(pat, "|([a-z0-9_.]*)(.*)") 438 | if altname then pat = pat2 end 439 | 440 | for p in gmatch(pat, ".") do 441 | local x = nil 442 | if p == "R" then 443 | x = map_gpr[band(rshift(op, rs), 31)] 444 | rs = rs - 5 445 | elseif p == "F" then 446 | x = "f"..band(rshift(op, rs), 31) 447 | rs = rs - 5 448 | elseif p == "A" then 449 | x = band(rshift(op, rs), 31) 450 | rs = rs - 5 451 | elseif p == "S" then 452 | x = arshift(lshift(op, 27-rs), 27) 453 | rs = rs - 5 454 | elseif p == "I" then 455 | x = arshift(lshift(op, 16), 16) 456 | elseif p == "U" then 457 | x = band(op, 0xffff) 458 | elseif p == "D" or p == "E" then 459 | local disp = arshift(lshift(op, 16), 16) 460 | if p == "E" then disp = band(disp, -4) end 461 | if last == "r0" then last = "0" end 462 | operands[#operands] = format("%d(%s)", disp, last) 463 | elseif p >= "2" and p <= "8" then 464 | local disp = band(rshift(op, rs), 31) * p 465 | if last == "r0" then last = "0" end 466 | operands[#operands] = format("%d(%s)", disp, last) 467 | elseif p == "H" then 468 | x = band(rshift(op, rs), 31) + lshift(band(op, 2), 4) 469 | rs = rs - 5 470 | elseif p == "M" then 471 | x = band(rshift(op, rs), 31) + band(op, 0x20) 472 | elseif p == "C" then 473 | x = condfmt(band(rshift(op, rs), 31)) 474 | rs = rs - 5 475 | elseif p == "B" then 476 | local bo = rshift(op, 21) 477 | local cond = band(rshift(op, 16), 31) 478 | local cn = "" 479 | rs = rs - 10 480 | if band(bo, 4) == 0 then 481 | cn = band(bo, 2) == 0 and "dnz" or "dz" 482 | if band(bo, 0x10) == 0 then 483 | cn = cn..(band(bo, 8) == 0 and "f" or "t") 484 | end 485 | if band(bo, 0x10) == 0 then x = condfmt(cond) end 486 | name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+") 487 | elseif band(bo, 0x10) == 0 then 488 | cn = map_cond[band(cond, 3) + (band(bo, 8) == 0 and 4 or 0)] 489 | if cond > 3 then x = "cr"..rshift(cond, 2) end 490 | name = name..(band(bo, 1) == band(rshift(op, 15), 1) and "-" or "+") 491 | end 492 | name = gsub(name, "_", cn) 493 | elseif p == "J" then 494 | x = arshift(lshift(op, 27-rs), 29-rs)*4 495 | if band(op, 2) == 0 then x = ctx.addr + pos + x end 496 | ctx.rel = x 497 | x = "0x"..tohex(x) 498 | elseif p == "K" then 499 | if band(op, 1) ~= 0 then name = name.."l" end 500 | if band(op, 2) ~= 0 then name = name.."a" end 501 | elseif p == "X" or p == "Y" then 502 | x = band(rshift(op, rs+2), 7) 503 | if x == 0 and p == "Y" then x = nil else x = "cr"..x end 504 | rs = rs - 5 505 | elseif p == "W" then 506 | x = "cr"..band(op, 7) 507 | elseif p == "Z" then 508 | x = band(rshift(op, rs-4), 255) 509 | rs = rs - 10 510 | elseif p == ">" then 511 | operands[#operands] = rshift(operands[#operands], 1) 512 | elseif p == "0" then 513 | if last == "r0" then 514 | operands[#operands] = nil 515 | if altname then name = altname end 516 | end 517 | elseif p == "L" then 518 | name = gsub(name, "_", band(op, 0x00200000) ~= 0 and "d" or "w") 519 | elseif p == "." then 520 | if band(op, 1) == 1 then name = name.."." end 521 | elseif p == "N" then 522 | if op == 0x60000000 then name = "nop"; break end 523 | elseif p == "~" then 524 | local n = #operands 525 | operands[n-1], operands[n] = operands[n], operands[n-1] 526 | elseif p == "=" then 527 | local n = #operands 528 | if last == operands[n-1] then 529 | operands[n] = nil 530 | name = altname 531 | end 532 | elseif p == "%" then 533 | local n = #operands 534 | if last == operands[n-1] and last == operands[n-2] then 535 | operands[n] = nil 536 | operands[n-1] = nil 537 | name = altname 538 | end 539 | elseif p == "-" then 540 | rs = rs - 5 541 | else 542 | assert(false) 543 | end 544 | if x then operands[#operands+1] = x; last = x end 545 | end 546 | 547 | return putop(ctx, name, operands) 548 | end 549 | 550 | ------------------------------------------------------------------------------ 551 | 552 | -- Disassemble a block of code. 553 | local function disass_block(ctx, ofs, len) 554 | if not ofs then ofs = 0 end 555 | local stop = len and ofs+len or #ctx.code 556 | stop = stop - stop % 4 557 | ctx.pos = ofs - ofs % 4 558 | ctx.rel = nil 559 | while ctx.pos < stop do disass_ins(ctx) end 560 | end 561 | 562 | -- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). 563 | local function create_(code, addr, out) 564 | local ctx = {} 565 | ctx.code = code 566 | ctx.addr = addr or 0 567 | ctx.out = out or io.write 568 | ctx.symtab = {} 569 | ctx.disass = disass_block 570 | ctx.hexdump = 8 571 | return ctx 572 | end 573 | 574 | -- Simple API: disassemble code (a string) at address and output via out. 575 | local function disass_(code, addr, out) 576 | create_(code, addr, out):disass() 577 | end 578 | 579 | -- Return register name for RID. 580 | local function regname_(r) 581 | if r < 32 then return map_gpr[r] end 582 | return "f"..(r-32) 583 | end 584 | 585 | -- Public module functions. 586 | module(...) 587 | 588 | create = create_ 589 | disass = disass_ 590 | regname = regname_ 591 | 592 | -------------------------------------------------------------------------------- /proj.win32/lua/jit/dis_x86.lua: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------- 2 | -- LuaJIT x86/x64 disassembler module. 3 | -- 4 | -- Copyright (C) 2005-2013 Mike Pall. All rights reserved. 5 | -- Released under the MIT license. See Copyright Notice in luajit.h 6 | ---------------------------------------------------------------------------- 7 | -- This is a helper module used by the LuaJIT machine code dumper module. 8 | -- 9 | -- Sending small code snippets to an external disassembler and mixing the 10 | -- output with our own stuff was too fragile. So I had to bite the bullet 11 | -- and write yet another x86 disassembler. Oh well ... 12 | -- 13 | -- The output format is very similar to what ndisasm generates. But it has 14 | -- been developed independently by looking at the opcode tables from the 15 | -- Intel and AMD manuals. The supported instruction set is quite extensive 16 | -- and reflects what a current generation Intel or AMD CPU implements in 17 | -- 32 bit and 64 bit mode. Yes, this includes MMX, SSE, SSE2, SSE3, SSSE3, 18 | -- SSE4.1, SSE4.2, SSE4a and even privileged and hypervisor (VMX/SVM) 19 | -- instructions. 20 | -- 21 | -- Notes: 22 | -- * The (useless) a16 prefix, 3DNow and pre-586 opcodes are unsupported. 23 | -- * No attempt at optimization has been made -- it's fast enough for my needs. 24 | -- * The public API may change when more architectures are added. 25 | ------------------------------------------------------------------------------ 26 | 27 | local type = type 28 | local sub, byte, format = string.sub, string.byte, string.format 29 | local match, gmatch, gsub = string.match, string.gmatch, string.gsub 30 | local lower, rep = string.lower, string.rep 31 | 32 | -- Map for 1st opcode byte in 32 bit mode. Ugly? Well ... read on. 33 | local map_opc1_32 = { 34 | --0x 35 | [0]="addBmr","addVmr","addBrm","addVrm","addBai","addVai","push es","pop es", 36 | "orBmr","orVmr","orBrm","orVrm","orBai","orVai","push cs","opc2*", 37 | --1x 38 | "adcBmr","adcVmr","adcBrm","adcVrm","adcBai","adcVai","push ss","pop ss", 39 | "sbbBmr","sbbVmr","sbbBrm","sbbVrm","sbbBai","sbbVai","push ds","pop ds", 40 | --2x 41 | "andBmr","andVmr","andBrm","andVrm","andBai","andVai","es:seg","daa", 42 | "subBmr","subVmr","subBrm","subVrm","subBai","subVai","cs:seg","das", 43 | --3x 44 | "xorBmr","xorVmr","xorBrm","xorVrm","xorBai","xorVai","ss:seg","aaa", 45 | "cmpBmr","cmpVmr","cmpBrm","cmpVrm","cmpBai","cmpVai","ds:seg","aas", 46 | --4x 47 | "incVR","incVR","incVR","incVR","incVR","incVR","incVR","incVR", 48 | "decVR","decVR","decVR","decVR","decVR","decVR","decVR","decVR", 49 | --5x 50 | "pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR","pushUR", 51 | "popUR","popUR","popUR","popUR","popUR","popUR","popUR","popUR", 52 | --6x 53 | "sz*pushaw,pusha","sz*popaw,popa","boundVrm","arplWmr", 54 | "fs:seg","gs:seg","o16:","a16", 55 | "pushUi","imulVrmi","pushBs","imulVrms", 56 | "insb","insVS","outsb","outsVS", 57 | --7x 58 | "joBj","jnoBj","jbBj","jnbBj","jzBj","jnzBj","jbeBj","jaBj", 59 | "jsBj","jnsBj","jpeBj","jpoBj","jlBj","jgeBj","jleBj","jgBj", 60 | --8x 61 | "arith!Bmi","arith!Vmi","arith!Bmi","arith!Vms", 62 | "testBmr","testVmr","xchgBrm","xchgVrm", 63 | "movBmr","movVmr","movBrm","movVrm", 64 | "movVmg","leaVrm","movWgm","popUm", 65 | --9x 66 | "nop*xchgVaR|pause|xchgWaR|repne nop","xchgVaR","xchgVaR","xchgVaR", 67 | "xchgVaR","xchgVaR","xchgVaR","xchgVaR", 68 | "sz*cbw,cwde,cdqe","sz*cwd,cdq,cqo","call farViw","wait", 69 | "sz*pushfw,pushf","sz*popfw,popf","sahf","lahf", 70 | --Ax 71 | "movBao","movVao","movBoa","movVoa", 72 | "movsb","movsVS","cmpsb","cmpsVS", 73 | "testBai","testVai","stosb","stosVS", 74 | "lodsb","lodsVS","scasb","scasVS", 75 | --Bx 76 | "movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi","movBRi", 77 | "movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI","movVRI", 78 | --Cx 79 | "shift!Bmu","shift!Vmu","retBw","ret","$lesVrm","$ldsVrm","movBmi","movVmi", 80 | "enterBwu","leave","retfBw","retf","int3","intBu","into","iretVS", 81 | --Dx 82 | "shift!Bm1","shift!Vm1","shift!Bmc","shift!Vmc","aamBu","aadBu","salc","xlatb", 83 | "fp*0","fp*1","fp*2","fp*3","fp*4","fp*5","fp*6","fp*7", 84 | --Ex 85 | "loopneBj","loopeBj","loopBj","sz*jcxzBj,jecxzBj,jrcxzBj", 86 | "inBau","inVau","outBua","outVua", 87 | "callVj","jmpVj","jmp farViw","jmpBj","inBad","inVad","outBda","outVda", 88 | --Fx 89 | "lock:","int1","repne:rep","rep:","hlt","cmc","testb!Bm","testv!Vm", 90 | "clc","stc","cli","sti","cld","std","incb!Bm","incd!Vm", 91 | } 92 | assert(#map_opc1_32 == 255) 93 | 94 | -- Map for 1st opcode byte in 64 bit mode (overrides only). 95 | local map_opc1_64 = setmetatable({ 96 | [0x06]=false, [0x07]=false, [0x0e]=false, 97 | [0x16]=false, [0x17]=false, [0x1e]=false, [0x1f]=false, 98 | [0x27]=false, [0x2f]=false, [0x37]=false, [0x3f]=false, 99 | [0x60]=false, [0x61]=false, [0x62]=false, [0x63]="movsxdVrDmt", [0x67]="a32:", 100 | [0x40]="rex*", [0x41]="rex*b", [0x42]="rex*x", [0x43]="rex*xb", 101 | [0x44]="rex*r", [0x45]="rex*rb", [0x46]="rex*rx", [0x47]="rex*rxb", 102 | [0x48]="rex*w", [0x49]="rex*wb", [0x4a]="rex*wx", [0x4b]="rex*wxb", 103 | [0x4c]="rex*wr", [0x4d]="rex*wrb", [0x4e]="rex*wrx", [0x4f]="rex*wrxb", 104 | [0x82]=false, [0x9a]=false, [0xc4]=false, [0xc5]=false, [0xce]=false, 105 | [0xd4]=false, [0xd5]=false, [0xd6]=false, [0xea]=false, 106 | }, { __index = map_opc1_32 }) 107 | 108 | -- Map for 2nd opcode byte (0F xx). True CISC hell. Hey, I told you. 109 | -- Prefix dependent MMX/SSE opcodes: (none)|rep|o16|repne, -|F3|66|F2 110 | local map_opc2 = { 111 | --0x 112 | [0]="sldt!Dmp","sgdt!Ump","larVrm","lslVrm",nil,"syscall","clts","sysret", 113 | "invd","wbinvd",nil,"ud1",nil,"$prefetch!Bm","femms","3dnowMrmu", 114 | --1x 115 | "movupsXrm|movssXrm|movupdXrm|movsdXrm", 116 | "movupsXmr|movssXmr|movupdXmr|movsdXmr", 117 | "movhlpsXrm$movlpsXrm|movsldupXrm|movlpdXrm|movddupXrm", 118 | "movlpsXmr||movlpdXmr", 119 | "unpcklpsXrm||unpcklpdXrm", 120 | "unpckhpsXrm||unpckhpdXrm", 121 | "movlhpsXrm$movhpsXrm|movshdupXrm|movhpdXrm", 122 | "movhpsXmr||movhpdXmr", 123 | "$prefetcht!Bm","hintnopVm","hintnopVm","hintnopVm", 124 | "hintnopVm","hintnopVm","hintnopVm","hintnopVm", 125 | --2x 126 | "movUmx$","movUmy$","movUxm$","movUym$","movUmz$",nil,"movUzm$",nil, 127 | "movapsXrm||movapdXrm", 128 | "movapsXmr||movapdXmr", 129 | "cvtpi2psXrMm|cvtsi2ssXrVmt|cvtpi2pdXrMm|cvtsi2sdXrVmt", 130 | "movntpsXmr|movntssXmr|movntpdXmr|movntsdXmr", 131 | "cvttps2piMrXm|cvttss2siVrXm|cvttpd2piMrXm|cvttsd2siVrXm", 132 | "cvtps2piMrXm|cvtss2siVrXm|cvtpd2piMrXm|cvtsd2siVrXm", 133 | "ucomissXrm||ucomisdXrm", 134 | "comissXrm||comisdXrm", 135 | --3x 136 | "wrmsr","rdtsc","rdmsr","rdpmc","sysenter","sysexit",nil,"getsec", 137 | "opc3*38",nil,"opc3*3a",nil,nil,nil,nil,nil, 138 | --4x 139 | "cmovoVrm","cmovnoVrm","cmovbVrm","cmovnbVrm", 140 | "cmovzVrm","cmovnzVrm","cmovbeVrm","cmovaVrm", 141 | "cmovsVrm","cmovnsVrm","cmovpeVrm","cmovpoVrm", 142 | "cmovlVrm","cmovgeVrm","cmovleVrm","cmovgVrm", 143 | --5x 144 | "movmskpsVrXm$||movmskpdVrXm$","sqrtpsXrm|sqrtssXrm|sqrtpdXrm|sqrtsdXrm", 145 | "rsqrtpsXrm|rsqrtssXrm","rcppsXrm|rcpssXrm", 146 | "andpsXrm||andpdXrm","andnpsXrm||andnpdXrm", 147 | "orpsXrm||orpdXrm","xorpsXrm||xorpdXrm", 148 | "addpsXrm|addssXrm|addpdXrm|addsdXrm","mulpsXrm|mulssXrm|mulpdXrm|mulsdXrm", 149 | "cvtps2pdXrm|cvtss2sdXrm|cvtpd2psXrm|cvtsd2ssXrm", 150 | "cvtdq2psXrm|cvttps2dqXrm|cvtps2dqXrm", 151 | "subpsXrm|subssXrm|subpdXrm|subsdXrm","minpsXrm|minssXrm|minpdXrm|minsdXrm", 152 | "divpsXrm|divssXrm|divpdXrm|divsdXrm","maxpsXrm|maxssXrm|maxpdXrm|maxsdXrm", 153 | --6x 154 | "punpcklbwPrm","punpcklwdPrm","punpckldqPrm","packsswbPrm", 155 | "pcmpgtbPrm","pcmpgtwPrm","pcmpgtdPrm","packuswbPrm", 156 | "punpckhbwPrm","punpckhwdPrm","punpckhdqPrm","packssdwPrm", 157 | "||punpcklqdqXrm","||punpckhqdqXrm", 158 | "movPrVSm","movqMrm|movdquXrm|movdqaXrm", 159 | --7x 160 | "pshufwMrmu|pshufhwXrmu|pshufdXrmu|pshuflwXrmu","pshiftw!Pmu", 161 | "pshiftd!Pmu","pshiftq!Mmu||pshiftdq!Xmu", 162 | "pcmpeqbPrm","pcmpeqwPrm","pcmpeqdPrm","emms|", 163 | "vmreadUmr||extrqXmuu$|insertqXrmuu$","vmwriteUrm||extrqXrm$|insertqXrm$", 164 | nil,nil, 165 | "||haddpdXrm|haddpsXrm","||hsubpdXrm|hsubpsXrm", 166 | "movVSmMr|movqXrm|movVSmXr","movqMmr|movdquXmr|movdqaXmr", 167 | --8x 168 | "joVj","jnoVj","jbVj","jnbVj","jzVj","jnzVj","jbeVj","jaVj", 169 | "jsVj","jnsVj","jpeVj","jpoVj","jlVj","jgeVj","jleVj","jgVj", 170 | --9x 171 | "setoBm","setnoBm","setbBm","setnbBm","setzBm","setnzBm","setbeBm","setaBm", 172 | "setsBm","setnsBm","setpeBm","setpoBm","setlBm","setgeBm","setleBm","setgBm", 173 | --Ax 174 | "push fs","pop fs","cpuid","btVmr","shldVmru","shldVmrc",nil,nil, 175 | "push gs","pop gs","rsm","btsVmr","shrdVmru","shrdVmrc","fxsave!Dmp","imulVrm", 176 | --Bx 177 | "cmpxchgBmr","cmpxchgVmr","$lssVrm","btrVmr", 178 | "$lfsVrm","$lgsVrm","movzxVrBmt","movzxVrWmt", 179 | "|popcntVrm","ud2Dp","bt!Vmu","btcVmr", 180 | "bsfVrm","bsrVrm|lzcntVrm|bsrWrm","movsxVrBmt","movsxVrWmt", 181 | --Cx 182 | "xaddBmr","xaddVmr", 183 | "cmppsXrmu|cmpssXrmu|cmppdXrmu|cmpsdXrmu","$movntiVmr|", 184 | "pinsrwPrWmu","pextrwDrPmu", 185 | "shufpsXrmu||shufpdXrmu","$cmpxchg!Qmp", 186 | "bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR","bswapVR", 187 | --Dx 188 | "||addsubpdXrm|addsubpsXrm","psrlwPrm","psrldPrm","psrlqPrm", 189 | "paddqPrm","pmullwPrm", 190 | "|movq2dqXrMm|movqXmr|movdq2qMrXm$","pmovmskbVrMm||pmovmskbVrXm", 191 | "psubusbPrm","psubuswPrm","pminubPrm","pandPrm", 192 | "paddusbPrm","padduswPrm","pmaxubPrm","pandnPrm", 193 | --Ex 194 | "pavgbPrm","psrawPrm","psradPrm","pavgwPrm", 195 | "pmulhuwPrm","pmulhwPrm", 196 | "|cvtdq2pdXrm|cvttpd2dqXrm|cvtpd2dqXrm","$movntqMmr||$movntdqXmr", 197 | "psubsbPrm","psubswPrm","pminswPrm","porPrm", 198 | "paddsbPrm","paddswPrm","pmaxswPrm","pxorPrm", 199 | --Fx 200 | "|||lddquXrm","psllwPrm","pslldPrm","psllqPrm", 201 | "pmuludqPrm","pmaddwdPrm","psadbwPrm","maskmovqMrm||maskmovdquXrm$", 202 | "psubbPrm","psubwPrm","psubdPrm","psubqPrm", 203 | "paddbPrm","paddwPrm","padddPrm","ud", 204 | } 205 | assert(map_opc2[255] == "ud") 206 | 207 | -- Map for three-byte opcodes. Can't wait for their next invention. 208 | local map_opc3 = { 209 | ["38"] = { -- [66] 0f 38 xx 210 | --0x 211 | [0]="pshufbPrm","phaddwPrm","phadddPrm","phaddswPrm", 212 | "pmaddubswPrm","phsubwPrm","phsubdPrm","phsubswPrm", 213 | "psignbPrm","psignwPrm","psigndPrm","pmulhrswPrm", 214 | nil,nil,nil,nil, 215 | --1x 216 | "||pblendvbXrma",nil,nil,nil, 217 | "||blendvpsXrma","||blendvpdXrma",nil,"||ptestXrm", 218 | nil,nil,nil,nil, 219 | "pabsbPrm","pabswPrm","pabsdPrm",nil, 220 | --2x 221 | "||pmovsxbwXrm","||pmovsxbdXrm","||pmovsxbqXrm","||pmovsxwdXrm", 222 | "||pmovsxwqXrm","||pmovsxdqXrm",nil,nil, 223 | "||pmuldqXrm","||pcmpeqqXrm","||$movntdqaXrm","||packusdwXrm", 224 | nil,nil,nil,nil, 225 | --3x 226 | "||pmovzxbwXrm","||pmovzxbdXrm","||pmovzxbqXrm","||pmovzxwdXrm", 227 | "||pmovzxwqXrm","||pmovzxdqXrm",nil,"||pcmpgtqXrm", 228 | "||pminsbXrm","||pminsdXrm","||pminuwXrm","||pminudXrm", 229 | "||pmaxsbXrm","||pmaxsdXrm","||pmaxuwXrm","||pmaxudXrm", 230 | --4x 231 | "||pmulddXrm","||phminposuwXrm", 232 | --Fx 233 | [0xf0] = "|||crc32TrBmt",[0xf1] = "|||crc32TrVmt", 234 | }, 235 | 236 | ["3a"] = { -- [66] 0f 3a xx 237 | --0x 238 | [0x00]=nil,nil,nil,nil,nil,nil,nil,nil, 239 | "||roundpsXrmu","||roundpdXrmu","||roundssXrmu","||roundsdXrmu", 240 | "||blendpsXrmu","||blendpdXrmu","||pblendwXrmu","palignrPrmu", 241 | --1x 242 | nil,nil,nil,nil, 243 | "||pextrbVmXru","||pextrwVmXru","||pextrVmSXru","||extractpsVmXru", 244 | nil,nil,nil,nil,nil,nil,nil,nil, 245 | --2x 246 | "||pinsrbXrVmu","||insertpsXrmu","||pinsrXrVmuS",nil, 247 | --4x 248 | [0x40] = "||dppsXrmu", 249 | [0x41] = "||dppdXrmu", 250 | [0x42] = "||mpsadbwXrmu", 251 | --6x 252 | [0x60] = "||pcmpestrmXrmu",[0x61] = "||pcmpestriXrmu", 253 | [0x62] = "||pcmpistrmXrmu",[0x63] = "||pcmpistriXrmu", 254 | }, 255 | } 256 | 257 | -- Map for VMX/SVM opcodes 0F 01 C0-FF (sgdt group with register operands). 258 | local map_opcvm = { 259 | [0xc1]="vmcall",[0xc2]="vmlaunch",[0xc3]="vmresume",[0xc4]="vmxoff", 260 | [0xc8]="monitor",[0xc9]="mwait", 261 | [0xd8]="vmrun",[0xd9]="vmmcall",[0xda]="vmload",[0xdb]="vmsave", 262 | [0xdc]="stgi",[0xdd]="clgi",[0xde]="skinit",[0xdf]="invlpga", 263 | [0xf8]="swapgs",[0xf9]="rdtscp", 264 | } 265 | 266 | -- Map for FP opcodes. And you thought stack machines are simple? 267 | local map_opcfp = { 268 | -- D8-DF 00-BF: opcodes with a memory operand. 269 | -- D8 270 | [0]="faddFm","fmulFm","fcomFm","fcompFm","fsubFm","fsubrFm","fdivFm","fdivrFm", 271 | "fldFm",nil,"fstFm","fstpFm","fldenvVm","fldcwWm","fnstenvVm","fnstcwWm", 272 | -- DA 273 | "fiaddDm","fimulDm","ficomDm","ficompDm", 274 | "fisubDm","fisubrDm","fidivDm","fidivrDm", 275 | -- DB 276 | "fildDm","fisttpDm","fistDm","fistpDm",nil,"fld twordFmp",nil,"fstp twordFmp", 277 | -- DC 278 | "faddGm","fmulGm","fcomGm","fcompGm","fsubGm","fsubrGm","fdivGm","fdivrGm", 279 | -- DD 280 | "fldGm","fisttpQm","fstGm","fstpGm","frstorDmp",nil,"fnsaveDmp","fnstswWm", 281 | -- DE 282 | "fiaddWm","fimulWm","ficomWm","ficompWm", 283 | "fisubWm","fisubrWm","fidivWm","fidivrWm", 284 | -- DF 285 | "fildWm","fisttpWm","fistWm","fistpWm", 286 | "fbld twordFmp","fildQm","fbstp twordFmp","fistpQm", 287 | -- xx C0-FF: opcodes with a pseudo-register operand. 288 | -- D8 289 | "faddFf","fmulFf","fcomFf","fcompFf","fsubFf","fsubrFf","fdivFf","fdivrFf", 290 | -- D9 291 | "fldFf","fxchFf",{"fnop"},nil, 292 | {"fchs","fabs",nil,nil,"ftst","fxam"}, 293 | {"fld1","fldl2t","fldl2e","fldpi","fldlg2","fldln2","fldz"}, 294 | {"f2xm1","fyl2x","fptan","fpatan","fxtract","fprem1","fdecstp","fincstp"}, 295 | {"fprem","fyl2xp1","fsqrt","fsincos","frndint","fscale","fsin","fcos"}, 296 | -- DA 297 | "fcmovbFf","fcmoveFf","fcmovbeFf","fcmovuFf",nil,{nil,"fucompp"},nil,nil, 298 | -- DB 299 | "fcmovnbFf","fcmovneFf","fcmovnbeFf","fcmovnuFf", 300 | {nil,nil,"fnclex","fninit"},"fucomiFf","fcomiFf",nil, 301 | -- DC 302 | "fadd toFf","fmul toFf",nil,nil, 303 | "fsub toFf","fsubr toFf","fdivr toFf","fdiv toFf", 304 | -- DD 305 | "ffreeFf",nil,"fstFf","fstpFf","fucomFf","fucompFf",nil,nil, 306 | -- DE 307 | "faddpFf","fmulpFf",nil,{nil,"fcompp"}, 308 | "fsubrpFf","fsubpFf","fdivrpFf","fdivpFf", 309 | -- DF 310 | nil,nil,nil,nil,{"fnstsw ax"},"fucomipFf","fcomipFf",nil, 311 | } 312 | assert(map_opcfp[126] == "fcomipFf") 313 | 314 | -- Map for opcode groups. The subkey is sp from the ModRM byte. 315 | local map_opcgroup = { 316 | arith = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" }, 317 | shift = { "rol", "ror", "rcl", "rcr", "shl", "shr", "sal", "sar" }, 318 | testb = { "testBmi", "testBmi", "not", "neg", "mul", "imul", "div", "idiv" }, 319 | testv = { "testVmi", "testVmi", "not", "neg", "mul", "imul", "div", "idiv" }, 320 | incb = { "inc", "dec" }, 321 | incd = { "inc", "dec", "callUmp", "$call farDmp", 322 | "jmpUmp", "$jmp farDmp", "pushUm" }, 323 | sldt = { "sldt", "str", "lldt", "ltr", "verr", "verw" }, 324 | sgdt = { "vm*$sgdt", "vm*$sidt", "$lgdt", "vm*$lidt", 325 | "smsw", nil, "lmsw", "vm*$invlpg" }, 326 | bt = { nil, nil, nil, nil, "bt", "bts", "btr", "btc" }, 327 | cmpxchg = { nil, "sz*,cmpxchg8bQmp,cmpxchg16bXmp", nil, nil, 328 | nil, nil, "vmptrld|vmxon|vmclear", "vmptrst" }, 329 | pshiftw = { nil, nil, "psrlw", nil, "psraw", nil, "psllw" }, 330 | pshiftd = { nil, nil, "psrld", nil, "psrad", nil, "pslld" }, 331 | pshiftq = { nil, nil, "psrlq", nil, nil, nil, "psllq" }, 332 | pshiftdq = { nil, nil, "psrlq", "psrldq", nil, nil, "psllq", "pslldq" }, 333 | fxsave = { "$fxsave", "$fxrstor", "$ldmxcsr", "$stmxcsr", 334 | nil, "lfenceDp$", "mfenceDp$", "sfenceDp$clflush" }, 335 | prefetch = { "prefetch", "prefetchw" }, 336 | prefetcht = { "prefetchnta", "prefetcht0", "prefetcht1", "prefetcht2" }, 337 | } 338 | 339 | ------------------------------------------------------------------------------ 340 | 341 | -- Maps for register names. 342 | local map_regs = { 343 | B = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", 344 | "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, 345 | B64 = { "al", "cl", "dl", "bl", "spl", "bpl", "sil", "dil", 346 | "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, 347 | W = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", 348 | "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" }, 349 | D = { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", 350 | "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" }, 351 | Q = { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", 352 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" }, 353 | M = { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", 354 | "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }, -- No x64 ext! 355 | X = { "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", 356 | "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15" }, 357 | } 358 | local map_segregs = { "es", "cs", "ss", "ds", "fs", "gs", "segr6", "segr7" } 359 | 360 | -- Maps for size names. 361 | local map_sz2n = { 362 | B = 1, W = 2, D = 4, Q = 8, M = 8, X = 16, 363 | } 364 | local map_sz2prefix = { 365 | B = "byte", W = "word", D = "dword", 366 | Q = "qword", 367 | M = "qword", X = "xword", 368 | F = "dword", G = "qword", -- No need for sizes/register names for these two. 369 | } 370 | 371 | ------------------------------------------------------------------------------ 372 | 373 | -- Output a nicely formatted line with an opcode and operands. 374 | local function putop(ctx, text, operands) 375 | local code, pos, hex = ctx.code, ctx.pos, "" 376 | local hmax = ctx.hexdump 377 | if hmax > 0 then 378 | for i=ctx.start,pos-1 do 379 | hex = hex..format("%02X", byte(code, i, i)) 380 | end 381 | if #hex > hmax then hex = sub(hex, 1, hmax)..". " 382 | else hex = hex..rep(" ", hmax-#hex+2) end 383 | end 384 | if operands then text = text.." "..operands end 385 | if ctx.o16 then text = "o16 "..text; ctx.o16 = false end 386 | if ctx.a32 then text = "a32 "..text; ctx.a32 = false end 387 | if ctx.rep then text = ctx.rep.." "..text; ctx.rep = false end 388 | if ctx.rex then 389 | local t = (ctx.rexw and "w" or "")..(ctx.rexr and "r" or "").. 390 | (ctx.rexx and "x" or "")..(ctx.rexb and "b" or "") 391 | if t ~= "" then text = "rex."..t.." "..text end 392 | ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false 393 | ctx.rex = false 394 | end 395 | if ctx.seg then 396 | local text2, n = gsub(text, "%[", "["..ctx.seg..":") 397 | if n == 0 then text = ctx.seg.." "..text else text = text2 end 398 | ctx.seg = false 399 | end 400 | if ctx.lock then text = "lock "..text; ctx.lock = false end 401 | local imm = ctx.imm 402 | if imm then 403 | local sym = ctx.symtab[imm] 404 | if sym then text = text.."\t->"..sym end 405 | end 406 | ctx.out(format("%08x %s%s\n", ctx.addr+ctx.start, hex, text)) 407 | ctx.mrm = false 408 | ctx.start = pos 409 | ctx.imm = nil 410 | end 411 | 412 | -- Clear all prefix flags. 413 | local function clearprefixes(ctx) 414 | ctx.o16 = false; ctx.seg = false; ctx.lock = false; ctx.rep = false 415 | ctx.rexw = false; ctx.rexr = false; ctx.rexx = false; ctx.rexb = false 416 | ctx.rex = false; ctx.a32 = false 417 | end 418 | 419 | -- Fallback for incomplete opcodes at the end. 420 | local function incomplete(ctx) 421 | ctx.pos = ctx.stop+1 422 | clearprefixes(ctx) 423 | return putop(ctx, "(incomplete)") 424 | end 425 | 426 | -- Fallback for unknown opcodes. 427 | local function unknown(ctx) 428 | clearprefixes(ctx) 429 | return putop(ctx, "(unknown)") 430 | end 431 | 432 | -- Return an immediate of the specified size. 433 | local function getimm(ctx, pos, n) 434 | if pos+n-1 > ctx.stop then return incomplete(ctx) end 435 | local code = ctx.code 436 | if n == 1 then 437 | local b1 = byte(code, pos, pos) 438 | return b1 439 | elseif n == 2 then 440 | local b1, b2 = byte(code, pos, pos+1) 441 | return b1+b2*256 442 | else 443 | local b1, b2, b3, b4 = byte(code, pos, pos+3) 444 | local imm = b1+b2*256+b3*65536+b4*16777216 445 | ctx.imm = imm 446 | return imm 447 | end 448 | end 449 | 450 | -- Process pattern string and generate the operands. 451 | local function putpat(ctx, name, pat) 452 | local operands, regs, sz, mode, sp, rm, sc, rx, sdisp 453 | local code, pos, stop = ctx.code, ctx.pos, ctx.stop 454 | 455 | -- Chars used: 1DFGIMPQRSTUVWXacdfgijmoprstuwxyz 456 | for p in gmatch(pat, ".") do 457 | local x = nil 458 | if p == "V" or p == "U" then 459 | if ctx.rexw then sz = "Q"; ctx.rexw = false 460 | elseif ctx.o16 then sz = "W"; ctx.o16 = false 461 | elseif p == "U" and ctx.x64 then sz = "Q" 462 | else sz = "D" end 463 | regs = map_regs[sz] 464 | elseif p == "T" then 465 | if ctx.rexw then sz = "Q"; ctx.rexw = false else sz = "D" end 466 | regs = map_regs[sz] 467 | elseif p == "B" then 468 | sz = "B" 469 | regs = ctx.rex and map_regs.B64 or map_regs.B 470 | elseif match(p, "[WDQMXFG]") then 471 | sz = p 472 | regs = map_regs[sz] 473 | elseif p == "P" then 474 | sz = ctx.o16 and "X" or "M"; ctx.o16 = false 475 | regs = map_regs[sz] 476 | elseif p == "S" then 477 | name = name..lower(sz) 478 | elseif p == "s" then 479 | local imm = getimm(ctx, pos, 1); if not imm then return end 480 | x = imm <= 127 and format("+0x%02x", imm) 481 | or format("-0x%02x", 256-imm) 482 | pos = pos+1 483 | elseif p == "u" then 484 | local imm = getimm(ctx, pos, 1); if not imm then return end 485 | x = format("0x%02x", imm) 486 | pos = pos+1 487 | elseif p == "w" then 488 | local imm = getimm(ctx, pos, 2); if not imm then return end 489 | x = format("0x%x", imm) 490 | pos = pos+2 491 | elseif p == "o" then -- [offset] 492 | if ctx.x64 then 493 | local imm1 = getimm(ctx, pos, 4); if not imm1 then return end 494 | local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end 495 | x = format("[0x%08x%08x]", imm2, imm1) 496 | pos = pos+8 497 | else 498 | local imm = getimm(ctx, pos, 4); if not imm then return end 499 | x = format("[0x%08x]", imm) 500 | pos = pos+4 501 | end 502 | elseif p == "i" or p == "I" then 503 | local n = map_sz2n[sz] 504 | if n == 8 and ctx.x64 and p == "I" then 505 | local imm1 = getimm(ctx, pos, 4); if not imm1 then return end 506 | local imm2 = getimm(ctx, pos+4, 4); if not imm2 then return end 507 | x = format("0x%08x%08x", imm2, imm1) 508 | else 509 | if n == 8 then n = 4 end 510 | local imm = getimm(ctx, pos, n); if not imm then return end 511 | if sz == "Q" and (imm < 0 or imm > 0x7fffffff) then 512 | imm = (0xffffffff+1)-imm 513 | x = format(imm > 65535 and "-0x%08x" or "-0x%x", imm) 514 | else 515 | x = format(imm > 65535 and "0x%08x" or "0x%x", imm) 516 | end 517 | end 518 | pos = pos+n 519 | elseif p == "j" then 520 | local n = map_sz2n[sz] 521 | if n == 8 then n = 4 end 522 | local imm = getimm(ctx, pos, n); if not imm then return end 523 | if sz == "B" and imm > 127 then imm = imm-256 524 | elseif imm > 2147483647 then imm = imm-4294967296 end 525 | pos = pos+n 526 | imm = imm + pos + ctx.addr 527 | if imm > 4294967295 and not ctx.x64 then imm = imm-4294967296 end 528 | ctx.imm = imm 529 | if sz == "W" then 530 | x = format("word 0x%04x", imm%65536) 531 | elseif ctx.x64 then 532 | local lo = imm % 0x1000000 533 | x = format("0x%02x%06x", (imm-lo) / 0x1000000, lo) 534 | else 535 | x = format("0x%08x", imm) 536 | end 537 | elseif p == "R" then 538 | local r = byte(code, pos-1, pos-1)%8 539 | if ctx.rexb then r = r + 8; ctx.rexb = false end 540 | x = regs[r+1] 541 | elseif p == "a" then x = regs[1] 542 | elseif p == "c" then x = "cl" 543 | elseif p == "d" then x = "dx" 544 | elseif p == "1" then x = "1" 545 | else 546 | if not mode then 547 | mode = ctx.mrm 548 | if not mode then 549 | if pos > stop then return incomplete(ctx) end 550 | mode = byte(code, pos, pos) 551 | pos = pos+1 552 | end 553 | rm = mode%8; mode = (mode-rm)/8 554 | sp = mode%8; mode = (mode-sp)/8 555 | sdisp = "" 556 | if mode < 3 then 557 | if rm == 4 then 558 | if pos > stop then return incomplete(ctx) end 559 | sc = byte(code, pos, pos) 560 | pos = pos+1 561 | rm = sc%8; sc = (sc-rm)/8 562 | rx = sc%8; sc = (sc-rx)/8 563 | if ctx.rexx then rx = rx + 8; ctx.rexx = false end 564 | if rx == 4 then rx = nil end 565 | end 566 | if mode > 0 or rm == 5 then 567 | local dsz = mode 568 | if dsz ~= 1 then dsz = 4 end 569 | local disp = getimm(ctx, pos, dsz); if not disp then return end 570 | if mode == 0 then rm = nil end 571 | if rm or rx or (not sc and ctx.x64 and not ctx.a32) then 572 | if dsz == 1 and disp > 127 then 573 | sdisp = format("-0x%x", 256-disp) 574 | elseif disp >= 0 and disp <= 0x7fffffff then 575 | sdisp = format("+0x%x", disp) 576 | else 577 | sdisp = format("-0x%x", (0xffffffff+1)-disp) 578 | end 579 | else 580 | sdisp = format(ctx.x64 and not ctx.a32 and 581 | not (disp >= 0 and disp <= 0x7fffffff) 582 | and "0xffffffff%08x" or "0x%08x", disp) 583 | end 584 | pos = pos+dsz 585 | end 586 | end 587 | if rm and ctx.rexb then rm = rm + 8; ctx.rexb = false end 588 | if ctx.rexr then sp = sp + 8; ctx.rexr = false end 589 | end 590 | if p == "m" then 591 | if mode == 3 then x = regs[rm+1] 592 | else 593 | local aregs = ctx.a32 and map_regs.D or ctx.aregs 594 | local srm, srx = "", "" 595 | if rm then srm = aregs[rm+1] 596 | elseif not sc and ctx.x64 and not ctx.a32 then srm = "rip" end 597 | ctx.a32 = false 598 | if rx then 599 | if rm then srm = srm.."+" end 600 | srx = aregs[rx+1] 601 | if sc > 0 then srx = srx.."*"..(2^sc) end 602 | end 603 | x = format("[%s%s%s]", srm, srx, sdisp) 604 | end 605 | if mode < 3 and 606 | (not match(pat, "[aRrgp]") or match(pat, "t")) then -- Yuck. 607 | x = map_sz2prefix[sz].." "..x 608 | end 609 | elseif p == "r" then x = regs[sp+1] 610 | elseif p == "g" then x = map_segregs[sp+1] 611 | elseif p == "p" then -- Suppress prefix. 612 | elseif p == "f" then x = "st"..rm 613 | elseif p == "x" then 614 | if sp == 0 and ctx.lock and not ctx.x64 then 615 | x = "CR8"; ctx.lock = false 616 | else 617 | x = "CR"..sp 618 | end 619 | elseif p == "y" then x = "DR"..sp 620 | elseif p == "z" then x = "TR"..sp 621 | elseif p == "t" then 622 | else 623 | error("bad pattern `"..pat.."'") 624 | end 625 | end 626 | if x then operands = operands and operands..", "..x or x end 627 | end 628 | ctx.pos = pos 629 | return putop(ctx, name, operands) 630 | end 631 | 632 | -- Forward declaration. 633 | local map_act 634 | 635 | -- Fetch and cache MRM byte. 636 | local function getmrm(ctx) 637 | local mrm = ctx.mrm 638 | if not mrm then 639 | local pos = ctx.pos 640 | if pos > ctx.stop then return nil end 641 | mrm = byte(ctx.code, pos, pos) 642 | ctx.pos = pos+1 643 | ctx.mrm = mrm 644 | end 645 | return mrm 646 | end 647 | 648 | -- Dispatch to handler depending on pattern. 649 | local function dispatch(ctx, opat, patgrp) 650 | if not opat then return unknown(ctx) end 651 | if match(opat, "%|") then -- MMX/SSE variants depending on prefix. 652 | local p 653 | if ctx.rep then 654 | p = ctx.rep=="rep" and "%|([^%|]*)" or "%|[^%|]*%|[^%|]*%|([^%|]*)" 655 | ctx.rep = false 656 | elseif ctx.o16 then p = "%|[^%|]*%|([^%|]*)"; ctx.o16 = false 657 | else p = "^[^%|]*" end 658 | opat = match(opat, p) 659 | if not opat then return unknown(ctx) end 660 | -- ctx.rep = false; ctx.o16 = false 661 | --XXX fails for 66 f2 0f 38 f1 06 crc32 eax,WORD PTR [esi] 662 | --XXX remove in branches? 663 | end 664 | if match(opat, "%$") then -- reg$mem variants. 665 | local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end 666 | opat = match(opat, mrm >= 192 and "^[^%$]*" or "%$(.*)") 667 | if opat == "" then return unknown(ctx) end 668 | end 669 | if opat == "" then return unknown(ctx) end 670 | local name, pat = match(opat, "^([a-z0-9 ]*)(.*)") 671 | if pat == "" and patgrp then pat = patgrp end 672 | return map_act[sub(pat, 1, 1)](ctx, name, pat) 673 | end 674 | 675 | -- Get a pattern from an opcode map and dispatch to handler. 676 | local function dispatchmap(ctx, opcmap) 677 | local pos = ctx.pos 678 | local opat = opcmap[byte(ctx.code, pos, pos)] 679 | pos = pos + 1 680 | ctx.pos = pos 681 | return dispatch(ctx, opat) 682 | end 683 | 684 | -- Map for action codes. The key is the first char after the name. 685 | map_act = { 686 | -- Simple opcodes without operands. 687 | [""] = function(ctx, name, pat) 688 | return putop(ctx, name) 689 | end, 690 | 691 | -- Operand size chars fall right through. 692 | B = putpat, W = putpat, D = putpat, Q = putpat, 693 | V = putpat, U = putpat, T = putpat, 694 | M = putpat, X = putpat, P = putpat, 695 | F = putpat, G = putpat, 696 | 697 | -- Collect prefixes. 698 | [":"] = function(ctx, name, pat) 699 | ctx[pat == ":" and name or sub(pat, 2)] = name 700 | if ctx.pos - ctx.start > 5 then return unknown(ctx) end -- Limit #prefixes. 701 | end, 702 | 703 | -- Chain to special handler specified by name. 704 | ["*"] = function(ctx, name, pat) 705 | return map_act[name](ctx, name, sub(pat, 2)) 706 | end, 707 | 708 | -- Use named subtable for opcode group. 709 | ["!"] = function(ctx, name, pat) 710 | local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end 711 | return dispatch(ctx, map_opcgroup[name][((mrm-(mrm%8))/8)%8+1], sub(pat, 2)) 712 | end, 713 | 714 | -- o16,o32[,o64] variants. 715 | sz = function(ctx, name, pat) 716 | if ctx.o16 then ctx.o16 = false 717 | else 718 | pat = match(pat, ",(.*)") 719 | if ctx.rexw then 720 | local p = match(pat, ",(.*)") 721 | if p then pat = p; ctx.rexw = false end 722 | end 723 | end 724 | pat = match(pat, "^[^,]*") 725 | return dispatch(ctx, pat) 726 | end, 727 | 728 | -- Two-byte opcode dispatch. 729 | opc2 = function(ctx, name, pat) 730 | return dispatchmap(ctx, map_opc2) 731 | end, 732 | 733 | -- Three-byte opcode dispatch. 734 | opc3 = function(ctx, name, pat) 735 | return dispatchmap(ctx, map_opc3[pat]) 736 | end, 737 | 738 | -- VMX/SVM dispatch. 739 | vm = function(ctx, name, pat) 740 | return dispatch(ctx, map_opcvm[ctx.mrm]) 741 | end, 742 | 743 | -- Floating point opcode dispatch. 744 | fp = function(ctx, name, pat) 745 | local mrm = getmrm(ctx); if not mrm then return incomplete(ctx) end 746 | local rm = mrm%8 747 | local idx = pat*8 + ((mrm-rm)/8)%8 748 | if mrm >= 192 then idx = idx + 64 end 749 | local opat = map_opcfp[idx] 750 | if type(opat) == "table" then opat = opat[rm+1] end 751 | return dispatch(ctx, opat) 752 | end, 753 | 754 | -- REX prefix. 755 | rex = function(ctx, name, pat) 756 | if ctx.rex then return unknown(ctx) end -- Only 1 REX prefix allowed. 757 | for p in gmatch(pat, ".") do ctx["rex"..p] = true end 758 | ctx.rex = true 759 | end, 760 | 761 | -- Special case for nop with REX prefix. 762 | nop = function(ctx, name, pat) 763 | return dispatch(ctx, ctx.rex and pat or "nop") 764 | end, 765 | } 766 | 767 | ------------------------------------------------------------------------------ 768 | 769 | -- Disassemble a block of code. 770 | local function disass_block(ctx, ofs, len) 771 | if not ofs then ofs = 0 end 772 | local stop = len and ofs+len or #ctx.code 773 | ofs = ofs + 1 774 | ctx.start = ofs 775 | ctx.pos = ofs 776 | ctx.stop = stop 777 | ctx.imm = nil 778 | ctx.mrm = false 779 | clearprefixes(ctx) 780 | while ctx.pos <= stop do dispatchmap(ctx, ctx.map1) end 781 | if ctx.pos ~= ctx.start then incomplete(ctx) end 782 | end 783 | 784 | -- Extended API: create a disassembler context. Then call ctx:disass(ofs, len). 785 | local function create_(code, addr, out) 786 | local ctx = {} 787 | ctx.code = code 788 | ctx.addr = (addr or 0) - 1 789 | ctx.out = out or io.write 790 | ctx.symtab = {} 791 | ctx.disass = disass_block 792 | ctx.hexdump = 16 793 | ctx.x64 = false 794 | ctx.map1 = map_opc1_32 795 | ctx.aregs = map_regs.D 796 | return ctx 797 | end 798 | 799 | local function create64_(code, addr, out) 800 | local ctx = create_(code, addr, out) 801 | ctx.x64 = true 802 | ctx.map1 = map_opc1_64 803 | ctx.aregs = map_regs.Q 804 | return ctx 805 | end 806 | 807 | -- Simple API: disassemble code (a string) at address and output via out. 808 | local function disass_(code, addr, out) 809 | create_(code, addr, out):disass() 810 | end 811 | 812 | local function disass64_(code, addr, out) 813 | create64_(code, addr, out):disass() 814 | end 815 | 816 | -- Return register name for RID. 817 | local function regname_(r) 818 | if r < 8 then return map_regs.D[r+1] end 819 | return map_regs.X[r-7] 820 | end 821 | 822 | local function regname64_(r) 823 | if r < 16 then return map_regs.Q[r+1] end 824 | return map_regs.X[r-15] 825 | end 826 | 827 | -- Public module functions. 828 | module(...) 829 | 830 | create = create_ 831 | create64 = create64_ 832 | disass = disass_ 833 | disass64 = disass64_ 834 | regname = regname_ 835 | regname64 = regname64_ 836 | 837 | --------------------------------------------------------------------------------