From e90fa63ebf22bd19751f3d10633f2f51bbd0926b Mon Sep 17 00:00:00 2001 From: msojocs Date: Sun, 18 Jun 2023 22:50:32 +0800 Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 3 +- src/include/wxml.h | 99 ++++--- src/wcc.cpp | 21 +- src/wxml/compiler.cpp | 32 +-- src/wxml/dom_lib/machine.cpp | 7 +- src/wxml/dom_lib/parse_exception.cpp | 18 ++ src/wxml/dom_lib/parser.cpp | 79 +++++- src/wxml/dom_lib/token.cpp | 2 +- src/wxml/dom_lib/tokenizer.cpp | 34 ++- test/defs.h | 380 +++++++++++++++++++++++++++ test/wcc.disassembly.cpp | 12 +- 11 files changed, 591 insertions(+), 96 deletions(-) create mode 100644 src/wxml/dom_lib/parse_exception.cpp create mode 100644 test/defs.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a21ca51..2a5aed8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,13 +11,14 @@ add_executable(wcc src/wxml/rewrite.cpp src/wxml/name_allocator.cpp src/wxml/string_templating/token.cpp + src/wxml/dom_lib/parse_exception.cpp src/wxml/dom_lib/token.cpp + src/wxml/dom_lib/machine.cpp src/wxml/dom_lib/tokenizer.cpp src/wxml/dom_lib/parser.cpp src/wxml/compiler.cpp src/wxml/dom_lib/str_cache.cpp src/wxml/dom_lib/wxml_dom.cpp - src/wxml/dom_lib/machine.cpp src/utils/string_utils.cpp src/utils/file.cpp ) diff --git a/src/include/wxml.h b/src/include/wxml.h index fb1fae4..ffe3a33 100644 --- a/src/include/wxml.h +++ b/src/include/wxml.h @@ -109,17 +109,56 @@ namespace WXML */ std::string ToAttrContent(); bool IsValidVariableName(std::string const&); - bool IsMatch(char const&); + bool IsMatch(char const*); bool GetTemplateContent(std::string const&, std::string&); ~Token(); }; + class ParseException + { + private: + /* data */ + public: + ParseException(/* args */); + ~ParseException(); + }; + + class Machine + { + private: + /* data */ + static bool bInited; // 初始化标志 + static int * TT; //类型不确定 + static int * STT; + int offset_0; // offset + 0 + int offset_1; // offset + 1 + int lineCount;// 当前处理的行数 offset + 2 + int lineLength; // 正在处理行的长度 offset + 3 + int offset_4; // offset + 4 + int offset_5; // offset + 5 + int offset_6; // offset + 6 + std::string filePath; // 文件路径 offset + 7 this+28 + + public: + Machine(/* args */); + Machine(std::string const& filePath); + ~Machine(); + void Reset(void); + void InitTransitTable(void); + void Feed(char,std::vector &,std::string &,std::vector &,int); + + }; + class Tokenizer { private: /* data */ + const char* fileContent; + int contentLength; + std::string fileName; + WXML::DOMLib::Machine machine; // this + 2 public: - Tokenizer(char const*,std::string const&); + Tokenizer(char const* fileContent, std::string const& filePath); Tokenizer(/* args */); ~Tokenizer(); int GetTokens( @@ -234,12 +273,16 @@ namespace WXML { private: /* data */ - WXML::DOMLib::WXMLDom dom; + std::shared_ptr dom; std::deque dequeStr; - std::vector offset_88; + std::vector tokenList; + int peekIndex = 0; + int offset_4; + int offset_8; int offset_128; - std::string offset_328; + std::string filePath; std::deque> dequeDom; + int v8; public: Parser(/* args */); ~Parser(); @@ -248,50 +291,24 @@ namespace WXML * wxml tag * view | */ - bool IsValidTag(std::string &); + static bool IsValidTag(std::string &); WXML::DOMLib::Token Peek(); bool Parse( char const*fileContent, // Str - std::string &, // a4 - std::string const&, // a5 + std::string & errorMessage, // a4 + std::string const& filePath, // a5 std::vector & // a6 ); - int Error(char const*, WXML::DOMLib::Token &); - WXML::DOMLib::WXMLDom GetParsed(); - std::string DOM(); - std::string DOMS(); + WXML::DOMLib::ParseException Error(char const*, WXML::DOMLib::Token *); + std::shared_ptr GetParsed(); + void DOM(); + void DOMS(); std::vector ATTR_LIST(); std::string ATTR(); }; - class Machine - { - private: - /* data */ - static bool bInited; // 初始化标志 - static int * TT; //类型不确定 - static int * STT; - int offset_0; // offset + 0 - int offset_1; // offset + 1 - int lineCount;// 当前处理的行数 offset + 2 - int lineLength; // 正在处理行的长度 offset + 3 - int offset_4; // offset + 4 - int offset_5; // offset + 5 - int offset_6; // offset + 6 - std::string filePath; // 文件路径 offset + 7 - - public: - Machine(/* args */); - Machine(std::string const& filePath); - ~Machine(); - void Reset(void); - void InitTransitTable(void); - void Feed(char,std::vector &,std::string &,std::vector &,int); - - }; - }; @@ -301,7 +318,7 @@ namespace WXML WXML::DOMLib::Parser ParseSource( std::string const& content, // 源码?a2 - std::string const& fileName, // 文件名? a3 + std::string const& filePath, // 文件名? a3 char lineEndMark, // '\n' a4 std::string const& gwxMark, // gwxMark a5 std::string const& fMark, // "f_" a6 @@ -317,9 +334,9 @@ namespace WXML std::string& errorMessage, // 错误信息 std::map& outputContentMap, // 输出1 编译后的代码映射 std::map& outputFuncMap, // 输出2 编译后的函数名 - std::map>&, + std::map>& dependencyListMap, std::map>& componentListMap, // vecFileContentMap componentList 页面使用的组件列表 - std::vector const&, // splitedData + std::vector const& splitedData, // splitedData std::map const&, // mapData1 bool, // isLLA std::string const&, // gwxMark diff --git a/src/wcc.cpp b/src/wcc.cpp index 9db0128..d5a825b 100644 --- a/src/wcc.cpp +++ b/src/wcc.cpp @@ -313,7 +313,6 @@ int main(int argc, const char **argv) { string componentName = getNextArg(xc_Or_completeCode_Param, splitMarkStr); componentList.push_back(componentName); - // TODO: 确认逻辑是否正确 auto it = std::find(allComponentList.begin(), allComponentList.end(), componentName); if (it == allComponentList.end()) { @@ -342,9 +341,9 @@ int main(int argc, const char **argv) splitedData[i] = path.substr(2); } } - map outputMap1; - map outputMap2; - map> vecFileContentMap2; + map outputContentMap; + map outputFuncMap; + map> dependencyListMap; const char off_5403C3[] = {'s', '\0', 'e', '\0'}; int compilerResult = 0; string errorMessage; @@ -352,9 +351,9 @@ int main(int argc, const char **argv) compilerResult = WXML::Compiler::CompileLazy( fileContentMap, errorMessage, - outputMap1, - outputMap2, // map - vecFileContentMap2, // std::map> + outputContentMap, + outputFuncMap, // map + dependencyListMap, // std::map> componentListMap, // componentListMap splitedData, mapData1, @@ -395,7 +394,7 @@ int main(int argc, const char **argv) "LOBAL__||{};var __globalThis=(typeof __vd_version_info__!=='undefined'&&typeof __vd_version_info__.globalThis!" "=='undefined')?__vd_version_info__.globalThis:(typeof window!=='undefined'?window:globalThis);"; data = data + helperCode; - outputMap1["__COMMON__"] = data; + outputContentMap["__COMMON__"] = data; } else { @@ -408,9 +407,9 @@ int main(int argc, const char **argv) "LOBAL__||{};var __globalThis=(typeof __vd_version_info__!=='undefined'&&typeof __vd_version_info__.globalThis!" "=='undefined')?__vd_version_info__.globalThis:(typeof window!=='undefined'?window:globalThis);"; commonData += helperCode; - commonData = commonData.append(outputMap1["__COMMON__"]); + commonData = commonData.append(outputContentMap["__COMMON__"]); - outputMap1["__COMMON__"] = commonData; + outputContentMap["__COMMON__"] = commonData; } string dep = ";var __WXML_DEP__=__WXML_DEP__||{};"; @@ -438,7 +437,7 @@ int main(int argc, const char **argv) } } // ??? - outputMap1["__COMMON__"].append(""); + outputContentMap["__COMMON__"].append(""); if (compilerResult) { // CompileLazy出现异常 diff --git a/src/wxml/compiler.cpp b/src/wxml/compiler.cpp index f792e1f..5ec4cc7 100644 --- a/src/wxml/compiler.cpp +++ b/src/wxml/compiler.cpp @@ -9,7 +9,7 @@ namespace WXML{ { WXML::DOMLib::Parser ParseSource( - std::string const& fileName, // 文件名a2 + std::string const& filePath, // 文件名a2 std::string const& content, // 源码a3 char lineEndMark, // '\n' a4 std::string const& gwxMark, // gwxMark a5 @@ -17,26 +17,26 @@ namespace WXML{ std::map const& fileContentMap, // fileContentMap a7 std::string& errorMessage, // 错误信息 a8 std::map>& result,// map a9 - std::map& map1,// ??? a10 + std::map& map1,// ??? a10 std::map& map2, // ??? a11 bool b1, // mark指定运算结果是否非0 a12 bool b2) // mark指定运算结果是否非0 a13 { WXML::DOMLib::Parser pResult; - bool isWxml = fileName.substr(fileName.length() - 5) == ".wxml"; + bool isWxml = filePath.substr(filePath.length() - 5) == ".wxml"; if (isWxml) { // parse bool parseResult = false; WXML::DOMLib::Parser v50; std::vector tokenList; // v102 - parseResult = v50.Parse(content.c_str(), errorMessage, fileName, tokenList); + parseResult = v50.Parse(content.c_str(), errorMessage, filePath, tokenList); if (parseResult) { // GetParsed - WXML::DOMLib::WXMLDom parseDom = v50.GetParsed(); - // result[fileName] = parseDom; + std::shared_ptr parseDom = v50.GetParsed(); + result[filePath] = parseDom; int a; int b; std::stringstream ss; @@ -77,7 +77,7 @@ namespace WXML{ if (/*??? && */ (gwxMark == "$gwx" || b2)) { std::stringstream errs; - errs << fileName; + errs << filePath; errs << ":"; // errs << v65; // 行号? errs << ":"; @@ -85,7 +85,7 @@ namespace WXML{ errs << ":"; // errs << v76; // 文件的某种路径 errs << " not found from "; - errs << fileName; + errs << filePath; errorMessage = errs.str(); // 清空 @@ -112,7 +112,7 @@ namespace WXML{ } else { - std::string data = "m_" + fileName; + std::string data = "m_" + filePath; data = data.append(":"); data = data.append(t); // GetFuncId @@ -123,7 +123,7 @@ namespace WXML{ throw compilerResult; } ss << "nv_require(\""; - std::string m = "m_" + fileName; + std::string m = "m_" + filePath; m = m.append(":"); // m = m.append(v74); // ss << ToStringCode(m); @@ -139,14 +139,14 @@ namespace WXML{ if (1) { - map1[fileName].assign(code); + map1[filePath].assign(code); } } } - else if(fileName.substr(fileName.length() - 4) == ".wxs") + else if(filePath.substr(filePath.length() - 4) == ".wxs") { - std::string p = "p_" + fileName; + std::string p = "p_" + filePath; // GetFuncId(map2) // compile_ns int compilerResultCode = 0; @@ -169,7 +169,7 @@ namespace WXML{ code << lineEndMark; std::string strCode = code.str(); - map1[fileName] = strCode; + map1[filePath] = strCode; } } @@ -213,8 +213,8 @@ namespace WXML{ { /* code */ WXML::DOMLib::Parser parseResult = WXML::Compiler::ParseSource( - it->second, // 源码?a2 - it->first, // 文件名 a3 + it->first, // 文件路径a2 + it->second, // 源码 a3 lineEndMark, // '\n' a4 gwxMark, // gwxMark a5 fMark, // "f_" a6 diff --git a/src/wxml/dom_lib/machine.cpp b/src/wxml/dom_lib/machine.cpp index 66eb3b9..c8d4b31 100644 --- a/src/wxml/dom_lib/machine.cpp +++ b/src/wxml/dom_lib/machine.cpp @@ -32,7 +32,7 @@ namespace WXML Machine::Machine(std::string const& filePath) { InitTransitTable(); - this->filePath. assign(filePath); + this->filePath.assign(filePath); } Machine::~Machine() @@ -183,7 +183,10 @@ namespace WXML } } - + void Machine::Reset() + { + + } } } \ No newline at end of file diff --git a/src/wxml/dom_lib/parse_exception.cpp b/src/wxml/dom_lib/parse_exception.cpp new file mode 100644 index 0000000..2e2455c --- /dev/null +++ b/src/wxml/dom_lib/parse_exception.cpp @@ -0,0 +1,18 @@ +#include "../../include/wxml.h" + +// WXML::DOMLib::ParseException +namespace WXML +{ + namespace DOMLib + { + + ParseException::ParseException(/* args */) + { + } + + ParseException::~ParseException() + { + } + + } +} \ No newline at end of file diff --git a/src/wxml/dom_lib/parser.cpp b/src/wxml/dom_lib/parser.cpp index c952d30..04c73c1 100644 --- a/src/wxml/dom_lib/parser.cpp +++ b/src/wxml/dom_lib/parser.cpp @@ -22,30 +22,89 @@ namespace WXML } bool Parser::Parse( char const* fileContent, - std::string & a4, - std::string const& a5, + std::string & errorMessage, + std::string const& filePath, std::vector & a6 ) { this->dequeStr.clear(); this->dequeDom.clear(); this->offset_128 = 4; - this->offset_328.assign(a5); - WXML::DOMLib::Tokenizer v15(fileContent, a5); - int ret = v15.GetTokens(this->offset_88, a4, a6); + this->filePath.assign(filePath); + WXML::DOMLib::Tokenizer v15(fileContent, filePath); + int ret = v15.GetTokens(this->tokenList, errorMessage, a6); if (!ret) { std::shared_ptr domPtr; - dom.tag = "root"; + this->dom->tag = "root"; domPtr.get()->tag = "root"; dequeDom.push_back(domPtr); // DOMS + this->DOMS(); } return ret == 0; } - // WXML::DOMLib::WXMLDom Parser::GetParsed() - // { - // return 0; - // } + + std::shared_ptr Parser::GetParsed() + { + return this->dom; + } + void Parser::DOM() + { + auto token = this->Peek(); + int v44; + if (v44) + { + if (v44 == 4) + { + return; + } + } + else + { + if (token.IsMatch("")) + { + this->peekIndex++; + auto token = this->Peek(); + auto tag = token.ToString(); + if (!WXML::DOMLib::Parser::IsValidTag(tag)) + { + throw this->Error("unexpected tag", 0); + } + this->peekIndex++; + + } + } + } + + WXML::DOMLib::Token Parser::Peek() + { + + return tokenList[this->peekIndex]; + } + + WXML::DOMLib::ParseException Parser::Error(char const*, WXML::DOMLib::Token *) + { + return WXML::DOMLib::ParseException(); + } + void Parser::DOMS() + { + while (true) + { + this->DOM(); + WXML::DOMLib::Token token = this->Peek(); + if (this->v8 == 4) + break; + if (token.IsMatch("offset_4 == this->offset_8) + { + throw WXML::DOMLib::Parser::Error("get tag end without start", nullptr); + } + break; + } + } + + } } } \ No newline at end of file diff --git a/src/wxml/dom_lib/token.cpp b/src/wxml/dom_lib/token.cpp index cd4d567..7a2e844 100644 --- a/src/wxml/dom_lib/token.cpp +++ b/src/wxml/dom_lib/token.cpp @@ -35,7 +35,7 @@ namespace WXML return v4; } - bool Token::IsMatch(char const&) + bool Token::IsMatch(char const*) { return true; } diff --git a/src/wxml/dom_lib/tokenizer.cpp b/src/wxml/dom_lib/tokenizer.cpp index 22a3057..36cd32b 100644 --- a/src/wxml/dom_lib/tokenizer.cpp +++ b/src/wxml/dom_lib/tokenizer.cpp @@ -5,23 +5,41 @@ namespace WXML namespace DOMLib { - Tokenizer::Tokenizer(char const*,std::string const&) - { - } - - Tokenizer::Tokenizer(/* args */) + Tokenizer::Tokenizer(char const* fileContent, std::string const& filePath) { + this->fileContent = fileContent; + this->contentLength = strlen(fileContent); + this->fileName = filePath; + WXML::DOMLib::Machine m(filePath); + this->machine = m; } Tokenizer::~Tokenizer() { } + int Tokenizer::GetTokens( - std::vector &, - std::string &, - std::vector & + std::vector &a2, + std::string &a3, + std::vector &a4 ) { + this->machine.Reset(); + if (this->fileContent) + { + for (int i = 0; i < this->contentLength; i++) + { + this->machine.Feed(this->fileContent[i], a2, a3, a4, 0); + } + this->machine.Feed(0, a2, a3, a4, 0); + + // TODO: 少了 + } + else + { + a3.replace(a3.begin(), a3.end(), "FATAL: no source was set or failed to allocate space for input source"); + return -1; + } return 0; } } diff --git a/test/defs.h b/test/defs.h new file mode 100644 index 0000000..e959478 --- /dev/null +++ b/test/defs.h @@ -0,0 +1,380 @@ +/* + + This file contains definitions used by the Hex-Rays decompiler output. + It has type definitions and convenience macros to make the + output more readable. + + Copyright (c) 2007-2017 Hex-Rays + +*/ + +#ifndef HEXRAYS_DEFS_H +#define HEXRAYS_DEFS_H + +#if defined(__GNUC__) + typedef long long ll; + typedef unsigned long long ull; + #define __int64 long long + #define __int32 int + #define __int16 short + #define __int8 char + #define MAKELL(num) num ## LL + #define FMT_64 "ll" +#elif defined(_MSC_VER) + typedef __int64 ll; + typedef unsigned __int64 ull; + #define MAKELL(num) num ## i64 + #define FMT_64 "I64" +#elif defined (__BORLANDC__) + typedef __int64 ll; + typedef unsigned __int64 ull; + #define MAKELL(num) num ## i64 + #define FMT_64 "L" +#else + #error "unknown compiler" +#endif +typedef unsigned int uint; +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned long ulong; + +typedef char int8; +typedef signed char sint8; +typedef unsigned char uint8; +typedef short int16; +typedef signed short sint16; +typedef unsigned short uint16; +typedef int int32; +typedef signed int sint32; +typedef unsigned int uint32; +typedef ll int64; +typedef ll sint64; +typedef ull uint64; + +// Partially defined types. They are used when the decompiler does not know +// anything about the type except its size. +#define _BYTE uint8 +#define _WORD uint16 +#define _DWORD uint32 +#define _QWORD uint64 +#if !defined(_MSC_VER) +#define _LONGLONG __int128 +#endif + +// Non-standard boolean types. They are used when the decompiler can not use +// the standard "bool" type because of the size mistmatch but the possible +// values are only 0 and 1. See also 'BOOL' type below. +typedef int8 _BOOL1; +typedef int16 _BOOL2; +typedef int32 _BOOL4; + +#ifndef _WINDOWS_ +typedef int8 BYTE; +typedef int16 WORD; +typedef int32 DWORD; +typedef int32 LONG; +typedef int BOOL; // uppercase BOOL is usually 4 bytes +#endif +typedef int64 QWORD; +#ifndef __cplusplus +typedef int bool; // we want to use bool in our C programs +#endif + +#define __pure // pure function: always returns the same value, has no + // side effects + +// Non-returning function +#if defined(__GNUC__) +#define __noreturn __attribute__((noreturn)) +#else +#define __noreturn __declspec(noreturn) +#endif + + +#ifndef NULL +#define NULL 0 +#endif + +// Some convenience macros to make partial accesses nicer +#define LAST_IND(x,part_type) (sizeof(x)/sizeof(part_type) - 1) +#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN +# define LOW_IND(x,part_type) LAST_IND(x,part_type) +# define HIGH_IND(x,part_type) 0 +#else +# define HIGH_IND(x,part_type) LAST_IND(x,part_type) +# define LOW_IND(x,part_type) 0 +#endif +// first unsigned macros: +#define BYTEn(x, n) (*((_BYTE*)&(x)+n)) +#define WORDn(x, n) (*((_WORD*)&(x)+n)) +#define DWORDn(x, n) (*((_DWORD*)&(x)+n)) + +#define LOBYTE(x) BYTEn(x,LOW_IND(x,_BYTE)) +#define LOWORD(x) WORDn(x,LOW_IND(x,_WORD)) +#define LODWORD(x) DWORDn(x,LOW_IND(x,_DWORD)) +#define HIBYTE(x) BYTEn(x,HIGH_IND(x,_BYTE)) +#define HIWORD(x) WORDn(x,HIGH_IND(x,_WORD)) +#define HIDWORD(x) DWORDn(x,HIGH_IND(x,_DWORD)) +#define BYTE1(x) BYTEn(x, 1) // byte 1 (counting from 0) +#define BYTE2(x) BYTEn(x, 2) +#define BYTE3(x) BYTEn(x, 3) +#define BYTE4(x) BYTEn(x, 4) +#define BYTE5(x) BYTEn(x, 5) +#define BYTE6(x) BYTEn(x, 6) +#define BYTE7(x) BYTEn(x, 7) +#define BYTE8(x) BYTEn(x, 8) +#define BYTE9(x) BYTEn(x, 9) +#define BYTE10(x) BYTEn(x, 10) +#define BYTE11(x) BYTEn(x, 11) +#define BYTE12(x) BYTEn(x, 12) +#define BYTE13(x) BYTEn(x, 13) +#define BYTE14(x) BYTEn(x, 14) +#define BYTE15(x) BYTEn(x, 15) +#define WORD1(x) WORDn(x, 1) +#define WORD2(x) WORDn(x, 2) // third word of the object, unsigned +#define WORD3(x) WORDn(x, 3) +#define WORD4(x) WORDn(x, 4) +#define WORD5(x) WORDn(x, 5) +#define WORD6(x) WORDn(x, 6) +#define WORD7(x) WORDn(x, 7) + +// now signed macros (the same but with sign extension) +#define SBYTEn(x, n) (*((int8*)&(x)+n)) +#define SWORDn(x, n) (*((int16*)&(x)+n)) +#define SDWORDn(x, n) (*((int32*)&(x)+n)) + +#define SLOBYTE(x) SBYTEn(x,LOW_IND(x,int8)) +#define SLOWORD(x) SWORDn(x,LOW_IND(x,int16)) +#define SLODWORD(x) SDWORDn(x,LOW_IND(x,int32)) +#define SHIBYTE(x) SBYTEn(x,HIGH_IND(x,int8)) +#define SHIWORD(x) SWORDn(x,HIGH_IND(x,int16)) +#define SHIDWORD(x) SDWORDn(x,HIGH_IND(x,int32)) +#define SBYTE1(x) SBYTEn(x, 1) +#define SBYTE2(x) SBYTEn(x, 2) +#define SBYTE3(x) SBYTEn(x, 3) +#define SBYTE4(x) SBYTEn(x, 4) +#define SBYTE5(x) SBYTEn(x, 5) +#define SBYTE6(x) SBYTEn(x, 6) +#define SBYTE7(x) SBYTEn(x, 7) +#define SBYTE8(x) SBYTEn(x, 8) +#define SBYTE9(x) SBYTEn(x, 9) +#define SBYTE10(x) SBYTEn(x, 10) +#define SBYTE11(x) SBYTEn(x, 11) +#define SBYTE12(x) SBYTEn(x, 12) +#define SBYTE13(x) SBYTEn(x, 13) +#define SBYTE14(x) SBYTEn(x, 14) +#define SBYTE15(x) SBYTEn(x, 15) +#define SWORD1(x) SWORDn(x, 1) +#define SWORD2(x) SWORDn(x, 2) +#define SWORD3(x) SWORDn(x, 3) +#define SWORD4(x) SWORDn(x, 4) +#define SWORD5(x) SWORDn(x, 5) +#define SWORD6(x) SWORDn(x, 6) +#define SWORD7(x) SWORDn(x, 7) + + +// Helper functions to represent some assembly instructions. + +#ifdef __cplusplus + +// compile time assertion +#define __CASSERT_N0__(l) COMPILE_TIME_ASSERT_ ## l +#define __CASSERT_N1__(l) __CASSERT_N0__(l) +#define CASSERT(cnd) typedef char __CASSERT_N1__(__LINE__) [(cnd) ? 1 : -1] + +// check that unsigned multiplication does not overflow +template bool is_mul_ok(T count, T elsize) +{ + CASSERT((T)(-1) > 0); // make sure T is unsigned + if ( elsize == 0 || count == 0 ) + return true; + return count <= ((T)(-1)) / elsize; +} + +// multiplication that saturates (yields the biggest value) instead of overflowing +// such a construct is useful in "operator new[]" +template bool saturated_mul(T count, T elsize) +{ + return is_mul_ok(count, elsize) ? count * elsize : T(-1); +} + +#include // for size_t + +// memcpy() with determined behavoir: it always copies +// from the start to the end of the buffer +// note: it copies byte by byte, so it is not equivalent to, for example, rep movsd +inline void *qmemcpy(void *dst, const void *src, size_t cnt) +{ + char *out = (char *)dst; + const char *in = (const char *)src; + while ( cnt > 0 ) + { + *out++ = *in++; + --cnt; + } + return dst; +} + +// Generate a reference to pair of operands +template int16 __PAIR__( int8 high, T low) { return ((( int16)high) << sizeof(high)*8) | uint8(low); } +template int32 __PAIR__( int16 high, T low) { return ((( int32)high) << sizeof(high)*8) | uint16(low); } +template int64 __PAIR__( int32 high, T low) { return ((( int64)high) << sizeof(high)*8) | uint32(low); } +template uint16 __PAIR__(uint8 high, T low) { return (((uint16)high) << sizeof(high)*8) | uint8(low); } +template uint32 __PAIR__(uint16 high, T low) { return (((uint32)high) << sizeof(high)*8) | uint16(low); } +template uint64 __PAIR__(uint32 high, T low) { return (((uint64)high) << sizeof(high)*8) | uint32(low); } + +// rotate left +template T __ROL__(T value, int count) +{ + const uint nbits = sizeof(T) * 8; + + if ( count > 0 ) + { + count %= nbits; + T high = value >> (nbits - count); + if ( T(-1) < 0 ) // signed value + high &= ~((T(-1) << count)); + value <<= count; + value |= high; + } + else + { + count = -count % nbits; + T low = value << (nbits - count); + value >>= count; + value |= low; + } + return value; +} + +inline uint8 __ROL1__(uint8 value, int count) { return __ROL__((uint8)value, count); } +inline uint16 __ROL2__(uint16 value, int count) { return __ROL__((uint16)value, count); } +inline uint32 __ROL4__(uint32 value, int count) { return __ROL__((uint32)value, count); } +inline uint64 __ROL8__(uint64 value, int count) { return __ROL__((uint64)value, count); } +inline uint8 __ROR1__(uint8 value, int count) { return __ROL__((uint8)value, -count); } +inline uint16 __ROR2__(uint16 value, int count) { return __ROL__((uint16)value, -count); } +inline uint32 __ROR4__(uint32 value, int count) { return __ROL__((uint32)value, -count); } +inline uint64 __ROR8__(uint64 value, int count) { return __ROL__((uint64)value, -count); } + +// carry flag of left shift +template int8 __MKCSHL__(T value, uint count) +{ + const uint nbits = sizeof(T) * 8; + count %= nbits; + + return (value >> (nbits-count)) & 1; +} + +// carry flag of right shift +template int8 __MKCSHR__(T value, uint count) +{ + return (value >> (count-1)) & 1; +} + +// sign flag +template int8 __SETS__(T x) +{ + if ( sizeof(T) == 1 ) + return int8(x) < 0; + if ( sizeof(T) == 2 ) + return int16(x) < 0; + if ( sizeof(T) == 4 ) + return int32(x) < 0; + return int64(x) < 0; +} + +// overflow flag of subtraction (x-y) +template int8 __OFSUB__(T x, U y) +{ + if ( sizeof(T) < sizeof(U) ) + { + U x2 = x; + int8 sx = __SETS__(x2); + return (sx ^ __SETS__(y)) & (sx ^ __SETS__(x2-y)); + } + else + { + T y2 = y; + int8 sx = __SETS__(x); + return (sx ^ __SETS__(y2)) & (sx ^ __SETS__(x-y2)); + } +} + +// overflow flag of addition (x+y) +template int8 __OFADD__(T x, U y) +{ + if ( sizeof(T) < sizeof(U) ) + { + U x2 = x; + int8 sx = __SETS__(x2); + return ((1 ^ sx) ^ __SETS__(y)) & (sx ^ __SETS__(x2+y)); + } + else + { + T y2 = y; + int8 sx = __SETS__(x); + return ((1 ^ sx) ^ __SETS__(y2)) & (sx ^ __SETS__(x+y2)); + } +} + +// carry flag of subtraction (x-y) +template int8 __CFSUB__(T x, U y) +{ + int size = sizeof(T) > sizeof(U) ? sizeof(T) : sizeof(U); + if ( size == 1 ) + return uint8(x) < uint8(y); + if ( size == 2 ) + return uint16(x) < uint16(y); + if ( size == 4 ) + return uint32(x) < uint32(y); + return uint64(x) < uint64(y); +} + +// carry flag of addition (x+y) +template int8 __CFADD__(T x, U y) +{ + int size = sizeof(T) > sizeof(U) ? sizeof(T) : sizeof(U); + if ( size == 1 ) + return uint8(x) > uint8(x+y); + if ( size == 2 ) + return uint16(x) > uint16(x+y); + if ( size == 4 ) + return uint32(x) > uint32(x+y); + return uint64(x) > uint64(x+y); +} + +#else +// The following definition is not quite correct because it always returns +// uint64. The above C++ functions are good, though. +#define __PAIR__(high, low) (((uint64)(high)<>y) +#define __CFADD__(x, y) invalid_operation // Generate carry flag for (x+y) +#define __CFSUB__(x, y) invalid_operation // Generate carry flag for (x-y) +#define __OFADD__(x, y) invalid_operation // Generate overflow flag for (x+y) +#define __OFSUB__(x, y) invalid_operation // Generate overflow flag for (x-y) +#endif + +// No definition for rcl/rcr because the carry flag is unknown +#define __RCL__(x, y) invalid_operation // Rotate left thru carry +#define __RCR__(x, y) invalid_operation // Rotate right thru carry +#define __MKCRCL__(x, y) invalid_operation // Generate carry flag for a RCL +#define __MKCRCR__(x, y) invalid_operation // Generate carry flag for a RCR +#define __SETP__(x, y) invalid_operation // Generate parity flag for (x-y) + +// In the decompilation listing there are some objects declarared as _UNKNOWN +// because we could not determine their types. Since the C compiler does not +// accept void item declarations, we replace them by anything of our choice, +// for example a char: + +#define _UNKNOWN char + +#ifdef _MSC_VER +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#endif + +#endif // HEXRAYS_DEFS_H \ No newline at end of file diff --git a/test/wcc.disassembly.cpp b/test/wcc.disassembly.cpp index 90dad67..bb11bcb 100644 --- a/test/wcc.disassembly.cpp +++ b/test/wcc.disassembly.cpp @@ -5,7 +5,7 @@ */ #include -#include +#include "defs.h" #include @@ -23097,7 +23097,7 @@ void __usercall WXML::DOMLib::Parser::DOM(_DWORD *a1@, WXML::DOMLib::Parser WXML::DOMLib::Parser::Error(v29, (WXML::DOMLib::Parser *)a1, "unexpected token", 0); __cxa_throw( v29, - (struct type_info *)&`typeinfo for'WXML::DOMLib::ParseException, + (struct type_info *)&`typeinfo for WXML::DOMLib::ParseException, WXML::DOMLib::ParseException::~ParseException); } ++a1[25]; @@ -23119,7 +23119,7 @@ LABEL_27: WXML::DOMLib::Parser::Error(v32, (WXML::DOMLib::Parser *)a1, "unexpected token", 0); __cxa_throw( v32, - (struct type_info *)&`typeinfo for'WXML::DOMLib::ParseException, + (struct type_info *)&`typeinfo for WXML::DOMLib::ParseException, WXML::DOMLib::ParseException::~ParseException); } if ( WXML::DOMLib::Token::IsMatch((int)v43, (WXML::DOMLib::Token *)", WXML: WXML::DOMLib::Parser::Error(exception, a1, "get tag end without start", 0); __cxa_throw( exception, - (struct type_info *)&`typeinfo for'WXML::DOMLib::ParseException, + (struct type_info *)&`typeinfo for WXML::DOMLib::ParseException, WXML::DOMLib::ParseException::~ParseException); } break; @@ -190573,7 +190573,7 @@ LABEL_84: v126, (int)&v109); v68 = (int)WXML::Compiler::CompileLazy( - &v107, // fileContent + &v107, // fileContentMap (int *)v111, // errorMessage &v115, // outputMap &v101, // dict