├── .gitignore ├── Makefile ├── README.md ├── src ├── .clang_complete ├── .clang_complete.bak ├── HeaderSearchPath.h ├── Obfuscator.cpp ├── Obfuscator.h ├── ResourceManager.cpp ├── ResourceManager.h ├── StrategyManager.cpp ├── StrategyManager.h ├── Typedef.h ├── alg │ ├── Algorithm.cpp │ ├── Algorithm.h │ ├── FlattenCFG │ │ ├── ASTTraverserPlus.h │ │ ├── CFGFlattener.cpp │ │ ├── CFGFlattener.h │ │ ├── FlattenCFGTransformer.cpp │ │ ├── FlattenCFGTransformer.h │ │ ├── LocalDeclMover.cpp │ │ ├── LocalDeclMover.h │ │ ├── MoveLocalDeclToTop.h.bak │ │ ├── StmtPretransformer.cpp │ │ ├── StmtPretransformer.h │ │ ├── VarRenamer.cpp │ │ └── VarRenamer.h │ ├── InitParseConsumer.cpp │ ├── InitParseConsumer.h │ ├── SimplePrinter.cpp │ ├── SimplePrinter.h │ ├── SimplePrinterConsumer.cpp │ └── SimplePrinterConsumer.h ├── obfs.cpp ├── obfs.h ├── res │ ├── OptionTable.cpp │ ├── OptionTable.h │ └── Options.inc └── stdafx.h └── test ├── _.__array.cpp ├── _.__cond.cpp ├── _.__const.cpp ├── _.__for.cpp ├── _.__function.cpp ├── _.__gcd_ob.cpp ├── _.__map.cpp ├── _.__ref.cpp ├── _anoyomous.cpp ├── _array.cpp ├── _array.log ├── _badcase.cpp ├── _big.cpp ├── _bool.cpp ├── _cfg.cpp ├── _class.cpp ├── _cond.cpp ├── _cond.log ├── _const.cpp ├── _construct.cpp ├── _decl.cpp ├── _des.cpp ├── _do.cpp ├── _enum.cpp ├── _for.cpp ├── _for.log ├── _function.cpp ├── _gcd.cpp ├── _gcd.log ├── _gcd_ob.cpp ├── _gcd_ob.log ├── _getcfg.sh ├── _goto.cpp ├── _hdu3589.cpp ├── _hdu3589o.cpp ├── _hdu4121.cpp ├── _hdu4121o.cpp ├── _if.cpp ├── _init.cpp ├── _innerclass.cpp ├── _iteration.cpp ├── _label.cpp ├── _macro.cpp ├── _map.cpp ├── _memhack.cpp ├── _nested.cpp ├── _new.cpp ├── _ns.cpp ├── _operator.cpp ├── _paren.cpp ├── _pointer.cpp ├── _ptr.cpp ├── _ref.cpp ├── _struct.cpp ├── _switch.cpp ├── _test.cpp ├── _test.h ├── _tpl.cpp ├── _using.cpp ├── _using1.h ├── _using2.h ├── _vardecl.cpp ├── _while.cpp ├── a0.png └── a1.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Precompilered Header File 2 | *.pch 3 | *.gch 4 | 5 | # Compiled Object files 6 | *.slo 7 | *.lo 8 | *.o 9 | 10 | # Compiled Dynamic libraries 11 | *.so 12 | 13 | # Compiled Static libraries 14 | *.lai 15 | *.la 16 | *.a 17 | 18 | # Complied Dependencies files 19 | *.d 20 | 21 | # Executable Target File 22 | obfs 23 | a.out 24 | 25 | # Swap file of vim 26 | *.swp 27 | 28 | # pack 29 | *.zip 30 | *.rar 31 | *.tar 32 | *.bz 33 | *.gz 34 | 35 | # test file 36 | @* 37 | _X* 38 | 39 | # config file for vim auto-complete plugins 40 | .ycm_extra_conf.pyc 41 | .ycm_extra_conf.py 42 | .clang_complete 43 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CXX = g++ 3 | 4 | ROOT = src 5 | REL_SUBDIR = . res alg alg/FlattenCFG 6 | SUBDIR = $(foreach dir,$(REL_SUBDIR),$(addprefix $(ROOT)/,$(dir))) 7 | INCLUDE = $(addprefix -I,$(ROOT)) 8 | 9 | TARGET = $(ROOT)/obfs 10 | SRCS = $(foreach dir,$(SUBDIR),$(wildcard $(dir)/[^@_]*.cpp)) 11 | OBJS = $(SRCS:.cpp=.o) 12 | 13 | # Rules for create dependencies 14 | .SUFFIXES: .d $(SUFFIXES) 15 | NODEPS = clean 16 | DEPFILES = $(SRCS:.cpp=.d) 17 | 18 | # Flags for compiling and linking 19 | DEBUGFLAG = -Wformat=0 -g -w -fno-rtti 20 | CXXFLAGS = $(DEBUGFLAG) -c $(INCLUDE) 21 | LLVMFLAGS = $(shell llvm-config --cxxflags) 22 | LDFLAGS = $(shell llvm-config --ldflags) 23 | LLVMLIBS = $(shell llvm-config --libs core mc mcparser bitreader) 24 | 25 | CLANGLIBS = \ 26 | -lclangTooling\ 27 | -lclangFrontendTool\ 28 | -lclangFrontend\ 29 | -lclangDriver\ 30 | -lclangSerialization\ 31 | -lclangCodeGen\ 32 | -lclangParse\ 33 | -lclangSema\ 34 | -lclangStaticAnalyzerFrontend\ 35 | -lclangStaticAnalyzerCheckers\ 36 | -lclangStaticAnalyzerCore\ 37 | -lclangAnalysis\ 38 | -lclangARCMigrate\ 39 | -lclangRewriteFrontend\ 40 | -lclangRewriteCore\ 41 | -lclangEdit\ 42 | -lclangASTMatchers \ 43 | -lclangAST\ 44 | -lclangLex\ 45 | -lclangBasic 46 | 47 | .PHONY: default all rebuild clean 48 | 49 | default: all 50 | 51 | ifeq (0, $(words $(findstring $(MAKECMDGOALS), $(NODEPS)))) 52 | -include $(DEPFILES) 53 | endif 54 | 55 | all: $(TARGET) 56 | 57 | rebuild: clean all 58 | 59 | $(TARGET): $(OBJS) Makefile 60 | @ echo ====== Link $@ 61 | $(CXX) $(OBJS) -o $@ $(CLANGLIBS) $(LLVMLIBS) $(LDFLAGS) 62 | 63 | $(OBJS): %.o:%.cpp %.d %.h 64 | @ echo ====== Build $@ 65 | $(CXX) $< $(CXXFLAGS) $(LLVMFLAGS) -o $@ 66 | 67 | %.d: %.cpp 68 | @ echo ====== Generate $@ 69 | $(CXX) $< -MM -MT '$(<:.cpp=.o) $@' $(CXXFLAGS) $(LLVMFLAGS) -MF $@ 70 | 71 | clean: 72 | @ echo ====== Clean 73 | rm -rf $(TARGET) $(OBJS) $(DEPFILES) 74 | 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | clangobfuscator 2 | =============== 3 | 4 | c/c++ obfuscator with clang lib 5 | 6 | 7 | #Change Log 8 | 9 | -------------------------------------------------------------------------------- /src/.clang_complete: -------------------------------------------------------------------------------- 1 | -I/usr/include/c++/4.6 2 | -I/usr/include/c++/4.6/i686-linux-gnu 3 | -I/usr/include/c++/4.6/backward 4 | -I/usr/lib/gcc/i686-linux-gnu/4.6/include 5 | -I/usr/lib/gcc/i686-linux-gnu/4.6/include-fixed 6 | -I/usr/include/i386-linux-gnu 7 | -I/usr/local/include 8 | -I/usr/include 9 | -D_DEBUG -D__NO_CTYPE_INLINE 10 | -D_GNU_SOURCE 11 | -D__STDC_CONSTANT_MACROS 12 | -D__STDC_FORMAT_MACROS 13 | -D__STDC_LIMIT_MACROS 14 | -I. 15 | -------------------------------------------------------------------------------- /src/.clang_complete.bak: -------------------------------------------------------------------------------- 1 | -I/usr/include/c++/4.6 2 | -I/usr/include/c++/4.6/i686-linux-gnu/. 3 | -I/usr/include/c++/4.6/backward 4 | -I/usr/lib/gcc/i686-linux-gnu/4.6.1/include 5 | -I/usr/local/include 6 | -I/usr/lib/gcc/i686-linux-gnu/4.6.1/include-fixed 7 | -I/usr/include/i386-linux-gnu 8 | -I/usr/include 9 | -D_DEBUG -D__NO_CTYPE_INLINE 10 | -D_GNU_SOURCE 11 | -D__STDC_CONSTANT_MACROS 12 | -D__STDC_FORMAT_MACROS 13 | -D__STDC_LIMIT_MACROS 14 | -include-pch ./stdafx.h.pch 15 | -------------------------------------------------------------------------------- /src/HeaderSearchPath.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_HSPATH_H 2 | #define OBFS_HSPATH_H 3 | 4 | //#include "stdafx.h" 5 | #include "clang/Basic/Version.h" 6 | #include 7 | using std::string; 8 | 9 | #define LLVM_PREFIX "/usr/local" 10 | const string HS_PATHS[] = { 11 | LLVM_PREFIX "/lib/clang/" CLANG_VERSION_STRING "/include", 12 | "/usr/local/include", 13 | "/usr/include", 14 | "/usr/include/linux", 15 | "/usr/include/c++/4.6", 16 | "/usr/include/c++/4.6/i686-linux-gnu", // linux of my laptop 17 | "/usr/include/c++/4.6/i486-linux-gnu", // linux of eb 18 | "/usr/include/c++/4.6/backward", 19 | "/usr/include/i386-linux-gnu/", 20 | }; 21 | #endif 22 | -------------------------------------------------------------------------------- /src/Obfuscator.cpp: -------------------------------------------------------------------------------- 1 | #include "Obfuscator.h" 2 | -------------------------------------------------------------------------------- /src/Obfuscator.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_OBFUSCATOR_H 2 | #define OBFS_OBFUSCATOR_H 3 | 4 | #include "stdafx.h" 5 | #include "ResourceManager.h" 6 | #include "StrategyManager.h" 7 | 8 | using namespace std; 9 | using namespace clang; 10 | 11 | class Obfuscator { 12 | OwningPtr resMgr; 13 | OwningPtr staMgr; 14 | 15 | 16 | public: 17 | void init() { 18 | resMgr.reset(new ResourceManager()); 19 | staMgr.reset(new StrategyManager(*resMgr.get())); 20 | } 21 | 22 | bool doit(int argc, char** argv) { 23 | ResourceManager &RM = *resMgr.get(); 24 | RM.init(argc, argv); 25 | StrategyManager &SM = *staMgr.get(); 26 | SM.execute(); 27 | RM.rewriteToFile(); 28 | //string errInfo; 29 | //llvm::raw_fd_ostream fout(string("@"+srcFile).c_str(), errInfo); 30 | //RM.prettyPrint(fout); 31 | //fout.close(); 32 | return true; 33 | } 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/ResourceManager.cpp: -------------------------------------------------------------------------------- 1 | #include "ResourceManager.h" 2 | #include "res/OptionTable.h" 3 | #include "clang/AST/ASTContext.h" 4 | #include "clang/AST/Stmt.h" 5 | #include "clang/Basic/Diagnostic.h" 6 | #include "clang/Basic/FileManager.h" 7 | #include "clang/Basic/SourceManager.h" 8 | #include "clang/Basic/TargetInfo.h" 9 | #include "clang/Basic/TargetOptions.h" 10 | #include "clang/Frontend/CompilerInstance.h" 11 | #include "clang/Lex/Preprocessor.h" 12 | #include "clang/Parse/ParseAST.h" 13 | #include "llvm/ADT/DenseSet.h" 14 | #include 15 | #include 16 | #include // for mkdir 17 | using namespace clang; 18 | using std::string; 19 | using llvm::DenseSet; 20 | 21 | void ResourceManager::init(int argc, char** argv) { 22 | decls.clear(); 23 | compInst.reset(); 24 | rw.reset(); 25 | optTable.reset(); 26 | 27 | optTable.reset(new OptionTable(argc, argv)); 28 | 29 | compInst.reset(new CompilerInstance()); 30 | CompilerInvocation &compInvo = compInst->getInvocation(); 31 | HeaderSearchOptions &hsOpts = compInst->getHeaderSearchOpts(); 32 | hsOpts.UseBuiltinIncludes = 1; 33 | hsOpts.UseStandardSystemIncludes = 1; 34 | hsOpts.UseStandardCXXIncludes = 1; 35 | hsOpts.Verbose = 1; 36 | for(int i = 0, l = sizeof(HS_PATHS)/sizeof(string*); i < l; i++) { 37 | hsOpts.AddPath(HS_PATHS[i], 38 | clang::frontend::CXXSystem, 39 | //true, false, false); 40 | // FIXME what's the change in new version? 41 | false, false); 42 | } 43 | 44 | compInvo.setLangDefaults( 45 | compInst->getLangOpts(), 46 | IK_CXX, 47 | LangStandard::lang_cxx98); 48 | 49 | compInst->createDiagnostics(NULL, false); 50 | 51 | TargetOptions tarOpts; 52 | tarOpts.Triple = llvm::sys::getDefaultTargetTriple(); 53 | TargetInfo *tarInfo = TargetInfo::CreateTargetInfo( //FIXME: memory leak 54 | compInst->getDiagnostics(), 55 | &tarOpts); 56 | compInst->setTarget(tarInfo); 57 | 58 | compInst->createFileManager(); 59 | FileManager &fileMgr = compInst->getFileManager(); 60 | compInst->createSourceManager(fileMgr); 61 | SourceManager &srcMgr = compInst->getSourceManager(); 62 | compInst->createPreprocessor(); 63 | compInst->createASTContext(); 64 | compInst->setASTConsumer(new InitParseConsumer(this->decls, this->compInst.get())); 65 | Preprocessor &pp = compInst->getPreprocessor(); 66 | pp.getBuiltinInfo().InitializeBuiltins(pp.getIdentifierTable(), pp.getLangOpts()); 67 | 68 | compInst->createSema(TU_Complete, NULL); 69 | 70 | rw.reset(new Rewriter()); 71 | rw->setSourceMgr(srcMgr, compInst->getLangOpts()); 72 | } 73 | 74 | bool ResourceManager::initParseAST() { 75 | assert(optTable->getOption(options::Argument).size() == 1 && "No src file specified."); 76 | string srcFileFullName = optTable->getOption(options::Argument).front(); 77 | FileManager &fileMgr = compInst->getFileManager(); 78 | SourceManager &srcMgr = compInst->getSourceManager(); 79 | const FileEntry *fileIn = fileMgr.getFile(srcFileFullName); 80 | srcMgr.createMainFileID(fileIn); 81 | compInst->getDiagnosticClient().BeginSourceFile( 82 | compInst->getLangOpts(), 83 | &compInst->getPreprocessor()); 84 | /* 85 | ParseAST(compInst->getPreprocessor(), 86 | new InitParseConsumer(decls, compInst.get()), 87 | compInst->getASTContext()); 88 | */ 89 | ParseAST(compInst->getSema()); 90 | 91 | return true; 92 | } 93 | 94 | void ResourceManager::rewriteToFile() { 95 | SourceManager &srcMgr = compInst->getSourceManager(); 96 | DenseSet q; 97 | TranslationUnitDecl *decls = compInst->getASTContext().getTranslationUnitDecl(); 98 | for(TranslationUnitDecl::decl_iterator I = decls->decls_begin(), E = decls->decls_end(); 99 | I != E; ++I) { 100 | Decl *D = *I; 101 | SourceLocation Loc = D->getLocation(); 102 | if(Loc.isInvalid() || srcMgr.isInSystemHeader(Loc)) { 103 | continue; 104 | } 105 | FileID thisFileID = srcMgr.getFileID(D->getLocation()); 106 | q.insert(thisFileID); 107 | } 108 | const RewriteBuffer *rwBuf = NULL; 109 | string errInfo; 110 | OptionTable::OptValueListTy& baseOutDir = optTable->getOption(options::OPT_Directory); 111 | for(DenseSet::iterator 112 | I = q.begin(), IEend = q.end(); 113 | I != IEend; ++I){ 114 | FileID thisFileID = *I; 115 | rwBuf = rw->getRewriteBufferFor(thisFileID); 116 | string thisFileName = srcMgr.getFileEntryForID(thisFileID)->getName(); //FIXME: implemented as getFilename in clang3.2+ 117 | int filenamePos = thisFileName.find_last_of("/\\")+1; 118 | string pathName = thisFileName.substr(0, filenamePos); 119 | string fileName = thisFileName.substr(filenamePos, thisFileName.length()); 120 | // FIXME: Should output to a seperate dest dir set in the config option 121 | if(baseOutDir.empty()) { 122 | // no output dir specified 123 | thisFileName = pathName + "_._" + fileName; 124 | } else { 125 | // FIXME: base dir not trimed 126 | pathName = baseOutDir.front() + "/" + pathName; 127 | this->mkdirRecursively(pathName.c_str()); 128 | thisFileName = pathName + fileName; 129 | } 130 | if(rwBuf != NULL) { 131 | llvm::raw_fd_ostream fos(thisFileName.c_str(), errInfo); 132 | fos << string(rwBuf->begin(), rwBuf->end()); 133 | fos.close(); 134 | DPRINT("src %s rewrited.", thisFileName.c_str()); 135 | } else { 136 | DPRINT("src %s not changed.", thisFileName.c_str()); 137 | } 138 | } 139 | } 140 | 141 | bool ResourceManager::prettyPrint(llvm::raw_ostream &out) { 142 | ASTContext &Ctx = compInst->getASTContext(); 143 | PrintingPolicy policy = compInst->getASTContext().getPrintingPolicy(); 144 | NullStmt *nullSt = new (compInst->getASTContext()) NullStmt(SourceLocation()); 145 | SourceManager &srcMgr = compInst->getSourceManager(); 146 | 147 | DenseSet createdFileID; 148 | FileID lastFileID; 149 | OwningPtr fout; 150 | string errInfo = ""; 151 | TranslationUnitDecl *decls = compInst->getASTContext().getTranslationUnitDecl(); 152 | for(TranslationUnitDecl::decl_iterator I = decls->decls_begin(), E = decls->decls_end(); 153 | I != E; ++I) { 154 | //for(int i = 0; i < decls.size(); i++ ){ 155 | // for(DeclGroupRef::iterator 156 | // I = decls[i].begin(), E = decls[i].end(); 157 | // I != E; ++I) { 158 | Decl *D = *I; 159 | SourceLocation Loc = D->getLocation(); 160 | if(Loc.isInvalid() || srcMgr.isInSystemHeader(Loc)) { 161 | continue; 162 | } 163 | FileID thisFileID = srcMgr.getFileID(D->getLocation()); 164 | if(thisFileID != lastFileID) { 165 | if(fout) { 166 | fout.get()->close(); 167 | fout.reset(); 168 | } 169 | string thisFileName = srcMgr.getFileEntryForID(thisFileID)->getName(); //FIXME: implemented as getFilename in clang3.2+ 170 | thisFileName.insert(thisFileName.find_last_of("/\\")+1, "@"); 171 | unsigned flags = /*createdFileID.find(thisFileID) != createdFileID.end() ? */llvm::raw_fd_ostream::F_Append /*: 0*/; 172 | fout.reset(new llvm::raw_fd_ostream(thisFileName.c_str(), errInfo, flags)); 173 | lastFileID = thisFileID; 174 | createdFileID.insert(thisFileID); 175 | DPRINT("Open desfile %s", thisFileName.c_str()); 176 | } 177 | /* 178 | if(FunctionDecl *TD = dyn_cast(D)) { 179 | (*fout.get()) << TD->getQualifiedNameAsString(policy); 180 | TD->getBody()->printPretty(*fout.get(), 0, policy); 181 | } else if(FunctionTemplateDecl *TD = dyn_cast(D)) { 182 | (*fout.get()) << TD->getQualifiedNameAsString(); 183 | TD->getTemplatedDecl()->getBody()->printPretty(*fout.get(), 0, policy); 184 | } else { 185 | */ 186 | D->print(*fout.get(), policy); 187 | nullSt->printPretty(*fout.get(), NULL, policy); 188 | //} 189 | // } 190 | } 191 | if(fout){ 192 | fout.get()->close(); 193 | } 194 | 195 | return true; 196 | } 197 | 198 | // FIXME: Path seperator 199 | int ResourceManager::mkdirRecursively(const char* pathname, mode_t mode) { 200 | if(mode == 0) { 201 | // Directory default mode: 755 202 | mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; 203 | } 204 | string pathstr(pathname); 205 | int lastSep = -1, nowSep; 206 | while((nowSep = pathstr.find_first_of("/\\", lastSep+1)) != -1) { 207 | if(nowSep - lastSep > 1) { 208 | string tmp = pathstr.substr(0, nowSep); 209 | int err = mkdir(tmp.c_str(), mode); 210 | DPRINT("Create path [%s]: [%d]", tmp.c_str(), err); 211 | } 212 | lastSep = nowSep; 213 | } 214 | 215 | return 0; 216 | } 217 | 218 | -------------------------------------------------------------------------------- /src/ResourceManager.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_RESOURCEMANAGER_H 2 | #define OBFS_RESOURCEMANAGER_H 3 | 4 | #include "stdafx.h" 5 | #include "HeaderSearchPath.h" 6 | #include "Typedef.h" 7 | #include "res/OptionTable.h" 8 | #include "alg/InitParseConsumer.h" 9 | 10 | #include "clang/Frontend/CompilerInstance.h" 11 | #include "clang/Rewrite/Core/Rewriter.h" 12 | 13 | #include "llvm/ADT/OwningPtr.h" 14 | #include "llvm/Support/Host.h" 15 | #include "llvm/Support/raw_ostream.h" 16 | 17 | #include 18 | #include 19 | #include // for mkdir 20 | 21 | using clang::CompilerInstance; 22 | using clang::Rewriter; 23 | using llvm::OwningPtr; 24 | using std::string; 25 | 26 | class GlobalConfig; 27 | class ResourceManager; 28 | 29 | class ResourceManager { 30 | protected: 31 | OwningPtr compInst; 32 | OwningPtr rw; 33 | OwningPtr optTable; 34 | 35 | DeclGroupRefVec decls; 36 | 37 | public: 38 | ResourceManager(){} 39 | 40 | ~ResourceManager() { 41 | rw.reset(); 42 | DPRINT("rw reset."); 43 | optTable.reset(); 44 | DPRINT("optTable reset."); 45 | compInst.reset(); 46 | DPRINT("compInst reset."); 47 | } 48 | 49 | void init(int argc, char **argv); 50 | 51 | bool initParseAST(); 52 | 53 | inline string getRewriteFileName(string srcFileName) { 54 | srcFileName.insert(srcFileName.find_last_of("/\\")+1, "@"); 55 | return srcFileName; 56 | } 57 | 58 | void rewriteToFile(); 59 | 60 | bool prettyPrint(llvm::raw_ostream &out); 61 | 62 | CompilerInstance& getCompilerInstance() { 63 | return *compInst.get(); 64 | } 65 | 66 | Rewriter& getRewriter() { 67 | return *rw.get(); 68 | } 69 | 70 | OptionTable& getOptionTable() { 71 | return *optTable.get(); 72 | } 73 | 74 | DeclGroupRefVec& getDeclGroupRefVec() { 75 | return decls; 76 | } 77 | 78 | //TODO TopLevelDeclGroup is in DeclContext::decls_begin()~decls_end() 79 | DeclGroupRef& updateAndGetDeclGroupRef(); 80 | DeclGroupRef& getDeclGroupRef(); 81 | 82 | int mkdirRecursively(const char *pathname, mode_t mode = 0); 83 | 84 | }; 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /src/StrategyManager.cpp: -------------------------------------------------------------------------------- 1 | #include "StrategyManager.h" 2 | #include "alg/Algorithm.h" 3 | #include "alg/FlattenCFG/FlattenCFGTransformer.h" 4 | #include "alg/SimplePrinter.h" 5 | using namespace std; 6 | using namespace clang; 7 | 8 | ErrCode 9 | StrategyManager::execute() { 10 | resMgr.initParseAST(); 11 | FlattenCFGTransformer(resMgr).execute(); 12 | SimplePrinter(resMgr).execute(); 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /src/StrategyManager.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_STRATEGYMANAGER_H 2 | #define OBFS_STRATEGYMANAGER_H 3 | 4 | #include "stdafx.h" 5 | #include "ResourceManager.h" 6 | 7 | class StrategyManager { 8 | protected: 9 | ResourceManager &resMgr; 10 | 11 | public: 12 | StrategyManager(ResourceManager &RM) 13 | : resMgr(RM) 14 | {} 15 | 16 | ~StrategyManager(){} 17 | 18 | ErrCode execute(); 19 | 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/Typedef.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_TYPEDEF_H 2 | #define OBFS_TYPEDEF_H 3 | 4 | //#include "stdafx.h" 5 | #include "clang/AST/DeclGroup.h" 6 | #include 7 | 8 | using std::vector; 9 | using clang::DeclGroupRef; 10 | 11 | typedef vector DeclGroupRefVec; 12 | typedef uint32_t ErrCode; 13 | 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/alg/Algorithm.cpp: -------------------------------------------------------------------------------- 1 | #include "alg/Algorithm.h" 2 | #include 3 | using namespace clang; 4 | using std::string; 5 | 6 | int32_t Algorithm::instCounter = 0; 7 | int Algorithm::NamedCounter = 0; 8 | int Algorithm::VarCounter = 0; 9 | int Algorithm::TagCounter = 0; 10 | int Algorithm::LabelCounter = 0; 11 | 12 | bool Algorithm::execute() { 13 | return true; 14 | } 15 | 16 | StmtPtrSmallVector* Algorithm::ICCopy(Stmt* s) { 17 | //FIXME memory leak 18 | StmtPtrSmallVector *res = new StmtPtrSmallVector(); 19 | for(Stmt::child_iterator I = s->child_begin(), E = s->child_end(); 20 | I != E; ++I){ 21 | if(*I) { 22 | res->push_back(*I); 23 | } 24 | } 25 | return res; 26 | } 27 | 28 | NullStmt* Algorithm::AddNewNullStmt() { 29 | return new (this->resMgr.getCompilerInstance().getASTContext()) 30 | NullStmt(SourceLocation()); 31 | } 32 | 33 | LabelStmt* Algorithm::AddNewLabel(Stmt *stBody) { 34 | //FIXME memory leak 35 | IdentifierInfo &info = getUniqueLabelName(); 36 | DPRINT("info %u: %s %d", (unsigned int)&info, info.getNameStart(), info.getBuiltinID()); 37 | //Sema &S = this->compInst.getSema(); 38 | //LabelDecl *lblD = this->compInst.getSema().LookupOrCreateLabel(&info, stBody->getLocStart()); 39 | //DPRINT("tud: %u\n", (unsigned int)compInst.getASTContext().getTranslationUnitDecl()); 40 | LabelDecl *lblD = LabelDecl::Create(compInst.getASTContext(), 41 | compInst.getASTContext().getTranslationUnitDecl(), 42 | SourceLocation(), 43 | &info); 44 | NullStmt *nullSt = new (this->compInst.getASTContext()) NullStmt(SourceLocation()); 45 | return new (this->compInst.getASTContext()) 46 | LabelStmt(SourceLocation(), lblD, 47 | stBody ? (Stmt*)stBody : (Stmt*)nullSt); 48 | } 49 | 50 | GotoStmt* Algorithm::AddNewGoto(LabelStmt *lblDes) { 51 | return new (this->resMgr.getCompilerInstance().getASTContext()) 52 | GotoStmt(lblDes->getDecl(), SourceLocation(), SourceLocation()); 53 | } 54 | 55 | IdentifierInfo& Algorithm::getUniqueIdentifier(string sname, int &ccnt) { 56 | IdentifierTable &idTable = this->compInst.getPreprocessor().getIdentifierTable(); 57 | int csz = idTable.size(); 58 | char lbl[128]; 59 | while(true) { 60 | sprintf(lbl, "%s%d", sname.c_str(), ccnt++); 61 | IdentifierInfo& info = idTable.get(string(lbl)); 62 | if(csz < idTable.size()) { 63 | return info; 64 | } 65 | } 66 | } 67 | 68 | bool Algorithm::renameVarDecl(NamedDecl *D) { 69 | D->setDeclName(DeclarationName(&getUniqueVarName())); 70 | return true; 71 | } 72 | 73 | bool Algorithm::renameTagDecl(NamedDecl *D) { 74 | D->setDeclName(DeclarationName(&getUniqueTagName())); 75 | return true; 76 | } 77 | 78 | bool Algorithm::renameNamedDecl(NamedDecl *D) { 79 | string lbl("____nameddecl____"); 80 | IdentifierInfo &info = getUniqueIdentifier(lbl, NamedCounter); 81 | D->setDeclName(DeclarationName(&info)); 82 | return true; 83 | } 84 | 85 | IdentifierInfo& Algorithm::getUniqueVarName() { 86 | const string lbl("____localvar____"); 87 | return getUniqueIdentifier(lbl, VarCounter); 88 | } 89 | 90 | 91 | IdentifierInfo& Algorithm::getUniqueTagName() { 92 | const string lbl("____localtag____"); 93 | return getUniqueIdentifier(lbl, TagCounter); 94 | } 95 | 96 | IdentifierInfo& Algorithm::getUniqueLabelName() { 97 | const string lbl("____label____"); 98 | return getUniqueIdentifier(lbl, LabelCounter); 99 | } 100 | 101 | Expr* Algorithm::BuildUnaryOperator(Expr *E, clang::UnaryOperatorKind OP) { 102 | Sema &S = this->resMgr.getCompilerInstance().getSema(); 103 | ExprResult ER = S.BuildUnaryOp(0, SourceLocation(), OP, E); 104 | assert(!ER.isInvalid()); 105 | return dyn_cast(ER.get()); 106 | } 107 | 108 | Expr* Algorithm::BuildBinaryOperator(Expr *LHS, Expr *RHS, clang::BinaryOperatorKind OP) { 109 | Sema &Actions = resMgr.getCompilerInstance().getSema(); 110 | ExprResult eRes = Actions.BuildBinOp(NULL, SourceLocation(), OP, LHS, RHS); 111 | assert(!eRes.isInvalid() && eRes.get()); 112 | return eRes.get(); 113 | } 114 | 115 | Expr* Algorithm::BuildCommonAssignExpr(Expr *LHS, Expr *RHS) { 116 | Sema &Actions = this->resMgr.getCompilerInstance().getSema(); 117 | ExprResult eRes = Actions.BuildBinOp(0, SourceLocation(), BO_Assign, LHS, RHS); 118 | assert(!eRes.isInvalid() && eRes.get()); 119 | return eRes.get(); 120 | } 121 | 122 | Expr* Algorithm::BuildVarAssignExpr(VarDecl *var, Expr* rExpr) { 123 | DeclRefExpr *dExpr = BuildVarDeclRefExpr(var); 124 | assert(dExpr != NULL); 125 | return this->BuildCommonAssignExpr(dExpr, rExpr); 126 | } 127 | 128 | BinaryOperator* Algorithm::BuildCommaExpr(Expr *lExpr, Expr *rExpr) { 129 | DPRINT("Comma BEGIN"); 130 | Sema &S = this->resMgr.getCompilerInstance().getSema(); 131 | ExprResult eRes = S.BuildBinOp(0, SourceLocation(), BO_Comma, lExpr, rExpr); 132 | assert(!eRes.isInvalid()); 133 | DPRINT("Comma END"); 134 | return dyn_cast(eRes.get()); 135 | } 136 | 137 | ParenExpr* Algorithm::BuildParenExpr(Expr *E) { 138 | ASTContext &Ctx = this->resMgr.getCompilerInstance().getASTContext(); 139 | return new (Ctx) 140 | ParenExpr(SourceLocation(), SourceLocation(), E); 141 | } 142 | 143 | DeclRefExpr* Algorithm::BuildVarDeclRefExpr(VarDecl *var) { 144 | ValueDecl *D = dyn_cast(var); 145 | assert(D && "cast to ValueDecl failed"); 146 | QualType Ty = var->getType(); 147 | ExprValueKind VK = VK_LValue; 148 | DeclarationNameInfo NameInfo(D->getDeclName(), SourceLocation()); 149 | 150 | DeclRefExpr *e = DeclRefExpr::Create( 151 | resMgr.getCompilerInstance().getASTContext(), 152 | NestedNameSpecifierLoc(), 153 | SourceLocation(), 154 | D, false, 155 | NameInfo, Ty, VK); 156 | // Sema::MarkDeclRefReferenced? 157 | return e; 158 | } 159 | 160 | 161 | ImplicitCastExpr* Algorithm::BuildImpCastExprToType(Expr *E, QualType Ty, CastKind CK) { 162 | Sema &S = this->resMgr.getCompilerInstance().getSema(); 163 | ExprResult eRes = S.ImpCastExprToType(E, Ty, CK); 164 | assert(!eRes.isInvalid()); 165 | return dyn_cast(eRes.get()); 166 | } 167 | 168 | DeclStmt* Algorithm::BuildDeclStmt(Decl *D) { 169 | return new (resMgr.getCompilerInstance().getASTContext()) 170 | DeclStmt(DeclGroupRef(D), SourceLocation(), SourceLocation()); 171 | } 172 | 173 | Expr* Algorithm::BuildTempObjectConstuctExpr(QualType Ty, Expr *expr) { 174 | ASTContext &Ctx = this->resMgr.getCompilerInstance().getASTContext(); 175 | TypeSourceInfo *TInfo = Ctx.CreateTypeSourceInfo(Ty); 176 | 177 | Sema &S = this->resMgr.getCompilerInstance().getSema(); 178 | //FIXME There is a hack here. 179 | //Sema::BuildCXXTypeConstructExpr will use SourceLocation().isInvalid() to determine 180 | //whether this is a InitList Construction 181 | ExprResult res = S.BuildCXXTypeConstructExpr(TInfo, 182 | SourceLocation().getLocWithOffset(1), 183 | expr ? MultiExprArg(&expr, 1) : MultiExprArg(), 184 | SourceLocation().getLocWithOffset(1)); 185 | assert(!res.isInvalid()); 186 | return res.get(); 187 | } 188 | 189 | Expr* Algorithm::BuildEqualCondExpr(Expr *EL, Expr *ER) { 190 | Sema &S = this->resMgr.getCompilerInstance().getSema(); 191 | ExprResult eRes = S.BuildBinOp(0, SourceLocation(), clang::BO_EQ, EL, ER); 192 | assert(!eRes.isInvalid()); 193 | return eRes.get(); 194 | } 195 | 196 | BinaryOperator* Algorithm::BuildRangeCondExpr(Expr *EV, Expr *EL, Expr *EH) { 197 | Sema &S = this->resMgr.getCompilerInstance().getSema(); 198 | ExprResult resLeft = S.BuildBinOp(0, SourceLocation(), clang::BO_LE, EL, EV); 199 | assert(!resLeft.isInvalid()); 200 | ExprResult resRight = S.BuildBinOp(0, SourceLocation(), clang::BO_LE, EV, EH); 201 | assert(!resRight.isInvalid()); 202 | ExprResult eRes = S.BuildBinOp(0, SourceLocation(), clang::BO_Add, resLeft.get(), resRight.get()); 203 | assert(!eRes.isInvalid()); 204 | return dyn_cast(eRes.get()); 205 | } 206 | 207 | Expr* Algorithm::BuildArraySubscriptExpr(Expr *Base, Expr **IdxList, unsigned int IdxNum) { 208 | //FIXME implement 209 | Sema &Actions = resMgr.getCompilerInstance().getSema(); 210 | clang::ExprResult LHS(Base); 211 | 212 | for(unsigned int I = 0; I < IdxNum; ++I) { 213 | //if (CheckProhibitedCXX11Attribute()) 214 | // return ExprError(); 215 | DPRINT("Build sub expr idx = %d", I); 216 | assert(IdxList[I] && "idx expr cannot be null"); 217 | ExprResult Idx(IdxList[I]); 218 | if(!LHS.isInvalid() && !Idx.isInvalid()) { 219 | LHS = Actions.ActOnArraySubscriptExpr(0, LHS.get(), SourceLocation(), Idx.get(), SourceLocation()); 220 | } else { 221 | DPRINT("Build sub expr failed at %d", I); 222 | LHS = ExprResult(true); 223 | break; 224 | } 225 | } 226 | 227 | assert(!LHS.isInvalid()); 228 | return LHS.get(); 229 | } 230 | 231 | IntegerLiteral* Algorithm::CreateIntegerLiteralX(int x) { 232 | ASTContext &Ctx = resMgr.getCompilerInstance().getSema().getASTContext(); 233 | return new (Ctx) 234 | IntegerLiteral(Ctx, llvm::APInt(32,x), Ctx.IntTy, SourceLocation()); 235 | } 236 | 237 | CXXBoolLiteralExpr* Algorithm::BuildCXXBoolLiteralExpr(bool val) { 238 | ASTContext &Ctx = resMgr.getCompilerInstance().getSema().getASTContext(); 239 | return new (Ctx) 240 | CXXBoolLiteralExpr(val, Ctx.BoolTy, SourceLocation()); 241 | } 242 | 243 | CompoundStmt* Algorithm::StVecToCompound(StmtPtrSmallVector *v){ 244 | //FIXME memory leak 245 | //remove null 246 | for(int i = v->size()-1; i >= 0; i--) { 247 | if(v->operator[](i) == NULL) { 248 | v->erase(v->begin() + i); 249 | } 250 | } 251 | return new (this->compInst.getASTContext()) 252 | CompoundStmt(this->compInst.getASTContext(), llvm::makeArrayRef(v->begin(), v->end()), SourceLocation(), SourceLocation()); 253 | } 254 | 255 | CompoundStmt* Algorithm::StmtToCompound(Stmt* S) { 256 | //FIXME memory leak 257 | if(isa(S)){ 258 | return dyn_cast(S); 259 | } 260 | return new (this->compInst.getASTContext()) 261 | CompoundStmt(this->compInst.getASTContext(), llvm::makeArrayRef(S), SourceLocation(), SourceLocation()); 262 | } 263 | 264 | 265 | StmtPtrSmallVector* Algorithm::RemoveNullStmtInVector(StmtPtrSmallVector *V) { 266 | int pNew = 0; 267 | for(int pOld = 0, pEnd = V->size(); 268 | pOld < pEnd; ++pOld) { 269 | Stmt *T = V->operator[](pOld); 270 | if(T && !isa(T)) { 271 | V->operator[](pNew++) = T; 272 | } 273 | } 274 | V->resize(pNew); 275 | return V; 276 | } 277 | 278 | CompoundStmt* Algorithm::RemoveNullChildren(CompoundStmt *S) { 279 | StmtPtrSmallVector *newBody = ICCopy(S); 280 | RemoveNullStmtInVector(newBody); 281 | ASTContext &Ctx = resMgr.getCompilerInstance().getASTContext(); 282 | S->setStmts(Ctx, &(*newBody->begin()), newBody->size()); 283 | delete newBody; 284 | return S; 285 | } 286 | 287 | bool Algorithm::replaceChild(Stmt *Parent, Stmt *OldChild, Stmt *NewChild) { 288 | if(!Parent) { 289 | DPRINT("Parent NULL"); 290 | return true; 291 | } 292 | for(Stmt::child_iterator I = Parent->child_begin(), IEnd = Parent->child_end(); 293 | I != IEnd; ++I) { 294 | if(*I == OldChild) { 295 | //memory leak 296 | *I = NewChild; 297 | return true; 298 | } 299 | } 300 | return false; 301 | } 302 | 303 | bool Algorithm::updateChildrenStmts(Stmt* fparent, StmtPtrSmallVector *fpv) { 304 | ASTContext &Ctx = this->compInst.getASTContext(); 305 | switch (fparent->getStmtClass()) { 306 | case Stmt::CompoundStmtClass: 307 | { 308 | CompoundStmt *st = dyn_cast(fparent); 309 | //RemoveNullStmtInVector(fpv); 310 | st->setStmts(Ctx, &(*fpv->begin()), fpv->size()); 311 | } 312 | break; 313 | case Stmt::ForStmtClass: 314 | { 315 | Stmt *st = fpv->size()>0 ? (fpv->front()) : (Stmt*)(new (Ctx) NullStmt(SourceLocation())); 316 | dyn_cast(fparent)->setBody(st); 317 | } 318 | break; 319 | case Stmt::DoStmtClass: 320 | { 321 | Stmt *st = fpv->size()>0 ? (fpv->front()) : (Stmt*)(new (Ctx) NullStmt(SourceLocation())); 322 | dyn_cast(fparent)->setBody(st); 323 | } 324 | break; 325 | case Stmt::WhileStmtClass: 326 | { 327 | Stmt *st = fpv->size()>0 ? (fpv->front()) : (Stmt*)(new (Ctx) NullStmt(SourceLocation())); 328 | dyn_cast(fparent)->setBody(st); 329 | break; 330 | } 331 | default: 332 | return false; 333 | } 334 | return true; 335 | } 336 | 337 | //create a new BuiltinType var 338 | //FIXME:DC is not used. Created var's isLocalVarDecl() unavailable 339 | DeclStmt* Algorithm::CreateVar(QualType Ty, DeclContext *DC, Expr *initList, VarDecl::StorageClass SC) { 340 | Sema &Actions = resMgr.getCompilerInstance().getSema(); 341 | ASTContext &Ctx = Actions.getASTContext(); 342 | if(DC == NULL) { 343 | DC = Ctx.getTranslationUnitDecl(); 344 | } 345 | //add ImpCast if needed 346 | //Use Sema::AddInitializerToDecl instead 347 | //if(initList) { 348 | // initList = BuildImpCastExprToType(initList, Ty, clang::CK_LValueToRValue); 349 | //} 350 | VarDecl *VD = VarDecl::Create(Ctx, DC, 351 | SourceLocation(), SourceLocation(), 352 | &getUniqueVarName(), Ty, NULL, 353 | SC); 354 | //FIXME: decl context 355 | //VD->setInit(initList); 356 | if(initList) { 357 | Actions.AddInitializerToDecl(VD, initList, false, true); 358 | } 359 | 360 | return BuildDeclStmt(VD); 361 | } 362 | 363 | //Create a new int var 364 | DeclStmt* Algorithm::CreateIntVar(DeclContext *DC, Expr *initVal, VarDecl::StorageClass SC) { 365 | return CreateVar(resMgr.getCompilerInstance().getSema().getASTContext().IntTy, DC, initVal, SC); 366 | } 367 | 368 | //create a new bool var 369 | DeclStmt* Algorithm::CreateBoolVar(DeclContext *DC, Expr *initVal, VarDecl::StorageClass SC) { 370 | return CreateVar(resMgr.getCompilerInstance().getSema().getASTContext().BoolTy, DC, initVal, SC); 371 | } 372 | 373 | Stmt* Algorithm::NullChildStmt(Stmt *Parent) { 374 | switch(Parent->getStmtClass()) { 375 | case Stmt::CompoundStmtClass: 376 | case Stmt::LabelStmtClass: 377 | return new(resMgr.getCompilerInstance().getASTContext()) NullStmt(SourceLocation()); 378 | 379 | default: 380 | return NULL; 381 | } 382 | } 383 | 384 | -------------------------------------------------------------------------------- /src/alg/Algorithm.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_ALG_ALGORITHM_H 2 | #define OBFS_ALG_ALGORITHM_H 3 | 4 | #include "stdafx.h" 5 | #include "ResourceManager.h" 6 | 7 | #include "clang/AST/ASTContext.h" 8 | #include "clang/AST/Expr.h" 9 | #include "clang/AST/Stmt.h" 10 | #include "clang/AST/Type.h" 11 | #include "clang/Basic/IdentifierTable.h" 12 | #include "clang/Basic/SourceLocation.h" 13 | #include "clang/Lex/Preprocessor.h" 14 | #include "clang/Sema/Sema.h" 15 | #include "llvm/ADT/SmallVector.h" 16 | #include 17 | 18 | using clang::CompilerInstance; 19 | using clang::Decl; 20 | using clang::NamedDecl; 21 | using clang::LabelDecl; 22 | using clang::VarDecl; 23 | using clang::Stmt; 24 | using clang::NullStmt; 25 | using clang::LabelStmt; 26 | using clang::GotoStmt; 27 | using clang::DeclStmt; 28 | using clang::DoStmt; 29 | using clang::WhileStmt; 30 | using clang::ForStmt; 31 | using clang::CompoundStmt; 32 | using clang::Expr; 33 | using clang::DeclRefExpr; 34 | using clang::ExprResult; 35 | using clang::IntegerLiteral; 36 | using clang::CXXBoolLiteralExpr; 37 | using clang::IdentifierInfo; 38 | using clang::QualType; 39 | using clang::CastKind; 40 | using clang::SourceLocation; 41 | using clang::ASTContext; 42 | using llvm::SmallVector; 43 | using std::string; 44 | 45 | using namespace clang; 46 | 47 | //FIXME move 48 | typedef SmallVector StmtPtrSmallVector; 49 | typedef SmallVector DeclPtrSmallVector; 50 | 51 | class Algorithm { 52 | public: 53 | virtual bool execute(); 54 | 55 | Algorithm(ResourceManager &RM) 56 | : resMgr(RM), 57 | compInst(RM.getCompilerInstance()), 58 | uid(++instCounter) 59 | {} 60 | 61 | virtual ~Algorithm() {} 62 | 63 | int32_t getUid(){ return uid; } 64 | 65 | protected: 66 | static int32_t instCounter; 67 | int32_t uid; 68 | ResourceManager &resMgr; 69 | CompilerInstance &compInst; 70 | 71 | static int NamedCounter; 72 | static int VarCounter; 73 | static int TagCounter; 74 | static int LabelCounter; 75 | 76 | StmtPtrSmallVector* ICCopy(Stmt* S); 77 | 78 | NullStmt* AddNewNullStmt(); 79 | 80 | LabelStmt* AddNewLabel(Stmt *stBody); 81 | 82 | GotoStmt* AddNewGoto(LabelStmt *lblDes); 83 | 84 | bool DeallocateStmt(Stmt *S) { 85 | resMgr.getCompilerInstance().getASTContext().Deallocate(S); 86 | } 87 | 88 | bool renameVarDecl(NamedDecl *D); 89 | 90 | bool renameTagDecl(NamedDecl *D); 91 | 92 | bool renameNamedDecl(NamedDecl *D); 93 | 94 | IdentifierInfo &getUniqueVarName(); 95 | 96 | IdentifierInfo &getUniqueTagName(); 97 | 98 | IdentifierInfo &getUniqueLabelName(); 99 | 100 | // create "op(E)" 101 | Expr* BuildUnaryOperator(Expr *E, clang::UnaryOperatorKind OP); 102 | 103 | // create "LHS op RHS" 104 | Expr* BuildBinaryOperator(Expr *LHS, Expr *RHS, clang::BinaryOperatorKind OP); 105 | 106 | // create stmt: "lExpr = rExpr" 107 | Expr* BuildVarAssignExpr(VarDecl *VD, Expr* ER); 108 | 109 | // create "LHS = RHS" 110 | Expr* BuildCommonAssignExpr(Expr* LHS, Expr* RHS); 111 | 112 | BinaryOperator* BuildCommaExpr(Expr *EL, Expr *ER); 113 | 114 | // create "(E)" 115 | ParenExpr* BuildParenExpr(Expr *E); 116 | 117 | // build DeclRefExpr using a VarDecl 118 | DeclRefExpr* BuildVarDeclRefExpr(VarDecl *VD); 119 | 120 | ImplicitCastExpr* BuildImpCastExprToType(Expr *E, QualType Ty, CastKind CK); 121 | 122 | // Build var/tag decl which will be placed at the begnning of a function body 123 | DeclStmt* BuildDeclStmt(Decl *D); 124 | 125 | // Build ObjectType(Expr) 126 | // This is used to make expr: "ObjectType xx = ObjectType(Expr)" 127 | // E can be NULL, when "ObjctType xx = ObjectType()" 128 | // Ty must be a desugaredType 129 | Expr* BuildTempObjectConstuctExpr(QualType Ty, Expr *E); 130 | 131 | //build EL == ER 132 | Expr* BuildEqualCondExpr(Expr *EL, Expr *ER); 133 | 134 | //build EL <= EV && EV <= ER 135 | BinaryOperator* BuildRangeCondExpr(Expr *EV, Expr *EL, Expr *EH); 136 | 137 | // Build "Base[idx1][idx2]...[idxN]" 138 | Expr* BuildArraySubscriptExpr(Expr* Base, Expr **IdxList, unsigned int IdxNum); 139 | 140 | IdentifierInfo& getUniqueIdentifier(string sname, int &ccnt); 141 | 142 | IntegerLiteral* CreateIntegerLiteralX(int X); 143 | 144 | CXXBoolLiteralExpr* BuildCXXBoolLiteralExpr(bool Val); 145 | 146 | //const_cast(E) 147 | CXXConstCastExpr* BuildCXXConstCastExpr(Expr *E, QualType Ty) { 148 | Sema &Sm = this->resMgr.getCompilerInstance().getSema(); 149 | //FIXME: TypeSourceInfo usage? 150 | TypeSourceInfo *DI = dyn_cast(Ty)->getTypeSourceInfo(); 151 | ExprResult ER = Sm.BuildCXXNamedCast(SourceLocation(), tok::kw_const_cast, 152 | DI, E, SourceLocation(), SourceLocation()); 153 | assert(!ER.isInvalid()); 154 | return dyn_cast(ER.get()); 155 | } 156 | 157 | //create a new BuiltinType var 158 | DeclStmt* CreateVar(QualType Ty, DeclContext *DC = NULL, Expr *initList = NULL, clang::StorageClass SC = clang::SC_None); 159 | // 160 | //Create a new int var 161 | DeclStmt* CreateIntVar(DeclContext *DC = NULL, Expr *initVal = NULL, clang::StorageClass SC = clang::SC_None); 162 | 163 | //create a new bool var 164 | DeclStmt* CreateBoolVar(DeclContext *DC = NULL, Expr *initVal = NULL, clang::StorageClass SC = clang::SC_None); 165 | 166 | //auto remove NULL(not NullStmt) 167 | CompoundStmt* StVecToCompound(StmtPtrSmallVector *v); 168 | 169 | CompoundStmt* StmtToCompound(Stmt* S); 170 | 171 | //remove NULL and NullStmt in V 172 | //if succeeded, return V 173 | StmtPtrSmallVector* RemoveNullStmtInVector(StmtPtrSmallVector *V); 174 | 175 | //remove NULL and NullStmt children of S 176 | //if succeeded, return S 177 | CompoundStmt* RemoveNullChildren(CompoundStmt *S); 178 | 179 | bool replaceChild(Stmt *Parent, Stmt *OldChild, Stmt *NewChild); 180 | 181 | // Will NOT automatically remove NULL or NullStmt in fpv 182 | bool updateChildrenStmts(Stmt* fparent, StmtPtrSmallVector *fpv); 183 | 184 | Stmt* NullChildStmt(Stmt *Parent); 185 | 186 | }; 187 | 188 | #endif 189 | -------------------------------------------------------------------------------- /src/alg/FlattenCFG/ASTTraverserPlus.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_ALG_ASTTRAVERSERPLUS_H 2 | #define OBFS_ALG_ASTTRAVERSERPLUS_H 3 | 4 | #include "stdafx.h" 5 | #include "clang/AST/RecursiveASTVisitor.h" 6 | #include "clang/Basic/SourceManager.h" 7 | #include "llvm/Support/raw_ostream.h" 8 | using namespace clang; 9 | 10 | template 11 | class ASTTraverserPlus: public RecursiveASTVisitor > { 12 | public: 13 | typedef ASTTraverserPlus ThisType; 14 | Derived &getDerived() { return *static_cast(this); } 15 | 16 | bool TraverseStmt(Stmt *S); 17 | bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); } 18 | bool VisitStmt(Stmt *S) { return true; } 19 | bool ExitStmt(Stmt *S){ return true; } 20 | 21 | bool TraverseDecl(Decl *D); 22 | bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); } 23 | bool VisitDecl(Decl *D) { return true; } 24 | bool ExitDecl(Decl *D){ return true; } 25 | 26 | // Traverse all decls in TranslationUnitDecl. 27 | // If SM is not NULL, then we'll use it to help skip system headers 28 | bool TraverseTranslationUnitDecl(TranslationUnitDecl *TUD, SourceManager *SM = NULL); 29 | bool BeforeTraverseDecl(Decl *D) { return true; } 30 | bool AfterTraverseDecl(Decl *D) { return true; } 31 | }; 32 | 33 | template 34 | bool ASTTraverserPlus::TraverseStmt(Stmt *S) { 35 | if(!S) { 36 | return true; 37 | } 38 | DPRINT("enter stmt %x (%s) | range ", (unsigned int)S, S->getStmtClassName()); 39 | RecursiveASTVisitor::TraverseStmt(S); 40 | DPRINT("exit stmt %x (%s)", (unsigned int)S, S->getStmtClassName()); 41 | getDerived().ExitStmt(S); 42 | return true; 43 | } 44 | 45 | template 46 | bool ASTTraverserPlus::TraverseDecl(Decl *D) { 47 | if(!D) { 48 | return true; 49 | } 50 | DPRINT("enter decl %x (%s)", (unsigned int)D, D->getDeclKindName()); 51 | RecursiveASTVisitor::TraverseDecl(D); 52 | DPRINT("exit decl %x (%s)", (unsigned int)D, D->getDeclKindName()); 53 | getDerived().ExitDecl(D); 54 | return true; 55 | } 56 | 57 | template 58 | bool ASTTraverserPlus::TraverseTranslationUnitDecl(TranslationUnitDecl *TUD, SourceManager *SM) { 59 | if(!TUD) { 60 | return true; 61 | } 62 | for(TranslationUnitDecl::decl_iterator I = TUD->decls_begin(), IEnd = TUD->decls_end(); 63 | I != IEnd; ++I) { 64 | Decl *D = *I; 65 | if(SM && SM->isInSystemHeader(D->getLocation())) { 66 | continue; 67 | } 68 | if(!getDerived().BeforeTraverseDecl(D)) { 69 | return false; 70 | } 71 | if(!getDerived().TraverseDecl(D)) { 72 | return false; 73 | } 74 | if(!getDerived().AfterTraverseDecl(D)) { 75 | return false; 76 | } 77 | } 78 | return true; 79 | } 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /src/alg/FlattenCFG/CFGFlattener.cpp: -------------------------------------------------------------------------------- 1 | #include "clang/Analysis/CFG.h" 2 | #include "clang/AST/ASTContext.h" 3 | #include "alg/FlattenCFG/ASTTraverserPlus.h" 4 | #include "alg/FlattenCFG/CFGFlattener.h" 5 | #include "llvm/ADT/DenseMap.h" 6 | 7 | using namespace clang; 8 | 9 | bool CFGFlattener::HandleDecl(Decl *D) { 10 | ASTContext &Ctx = resMgr.getCompilerInstance().getASTContext(); 11 | FunctionDecl *FD = dyn_cast(D); 12 | if(!FD) { 13 | DPRINT("pass non-function decl"); 14 | return true; 15 | } 16 | if(!FD->isThisDeclarationADefinition()) { 17 | DPRINT("pass non-definitition of functionDecl"); 18 | return true; 19 | } 20 | DPRINT("decl before flatten"); 21 | D->dump(); 22 | Stmt *S = D->getBody(); 23 | this->cfgraph.reset(CFG::buildCFG(D, D->getBody(), 24 | &Ctx, CFG::BuildOptions())); 25 | assert(cfgraph.get()); 26 | DPRINT("cfg before flattening"); 27 | cfgraph.get()->dump(Ctx.getLangOpts(), false); 28 | cfgraph.get()->viewCFG(Ctx.getLangOpts()); 29 | 30 | newgraph.rebind(cfgraph.get(), S); 31 | 32 | if(!isa(S)) { 33 | DPRINT("Not a CompoundStmt %x", (unsigned)S); 34 | return true; 35 | } 36 | 37 | // Do flattening 38 | CompoundStmt *CS = dyn_cast(S); 39 | DPRINT("CompoundStmt before flatten"); 40 | CS->dumpPretty(Ctx); 41 | StmtPtrSmallVector *newBody = new StmtPtrSmallVector(); 42 | // Add DeclStmt 43 | for(CompoundStmt::body_iterator I = CS->body_begin(), IEnd = CS->body_end(); 44 | I != IEnd; ++I) { 45 | Stmt *T = *I; 46 | if(isa(T)) { 47 | newBody->push_back(T); 48 | DPRINT("DeclStmt at the beginning met."); 49 | T->dump(); 50 | } 51 | } 52 | 53 | int SwiVarEntryValue = newgraph.EntryNode->Succs[0]->NodeID; 54 | int SwiVarExitValue = newgraph.ExitNode->NodeID; 55 | 56 | DeclStmt *stSwiVarDcl = CreateIntVar(NULL, CreateIntegerLiteralX(SwiVarEntryValue)); 57 | VarDecl *SwiVarDcl = dyn_cast(stSwiVarDcl->getSingleDecl()); 58 | newBody->push_back(stSwiVarDcl); 59 | // while stmt body be filled later 60 | WhileStmt *stWhile = new (Ctx) 61 | WhileStmt(Ctx, NULL, 62 | BuildBinaryOperator(BuildVarDeclRefExpr(SwiVarDcl), CreateIntegerLiteralX(SwiVarExitValue), clang::BO_NE), 63 | NULL, SourceLocation()); 64 | newBody->push_back(stWhile); 65 | 66 | SwitchStmt *stSwitch = new (Ctx) 67 | SwitchStmt(Ctx, NULL, BuildVarDeclRefExpr(SwiVarDcl)); 68 | stSwitch->setConditionVariable(Ctx, SwiVarDcl); 69 | 70 | stWhile->setBody(stSwitch); 71 | 72 | StmtPtrSmallVector swiBody; 73 | // Create CaseStmt for each block and add to SwitchStmt 74 | for(unsigned i = 0; i != newgraph.NumBlockIDs; ++i) { 75 | if(&newgraph.Nodes[i] == newgraph.EntryNode || 76 | & newgraph.Nodes[i] == newgraph.ExitNode) 77 | continue; 78 | CaseStmt *stCase = CreateCaseStmt(&newgraph.Nodes[i], SwiVarDcl); 79 | if(!stCase) 80 | continue; 81 | stSwitch->addSwitchCase(stCase); 82 | swiBody.push_back(stCase); 83 | } 84 | stSwitch->setBody(StVecToCompound(&swiBody)); 85 | DPRINT("New switch body create"); 86 | stSwitch->dumpPretty(Ctx); 87 | 88 | updateChildrenStmts(CS, newBody); 89 | DPRINT("New function body created."); 90 | CS->dumpPretty(Ctx); 91 | 92 | DPRINT("decl after flatten"); 93 | D->dump(); 94 | return true; 95 | } 96 | 97 | bool CFGFlattener::PrepareGraph(CFG *G) { 98 | assert(G); 99 | CFGBlock *Entry = &G->getEntry(), *Exit = &G->getExit(); 100 | for(CFG::iterator I = G->begin(), IEnd = G->end(); 101 | I != IEnd ; ++I) { 102 | CFGBlock *B = *I; 103 | if(!B){ 104 | DPRINT("CFGBlock null %dth", I - G->begin()); 105 | continue; 106 | } 107 | if(isTransparentBlock(B)) { 108 | DPRINT("transparent block this %u %x", B->getBlockID(), (unsigned)B); 109 | } 110 | for(CFGBlock::succ_iterator SuccI = B->succ_begin(), SuccIEnd = B->succ_end(); 111 | SuccI != SuccIEnd; ++SuccI) { 112 | //visit outcoming edge 113 | CFGBlock **pChild = SuccI, *&Child = *SuccI; 114 | if(Child == Exit) { 115 | continue; 116 | } 117 | if(!Child) { 118 | DPRINT("CFGElement null %x", (unsigned)pChild); 119 | continue; 120 | } 121 | if(isTransparentBlock(Child)) { 122 | DPRINT("transparent child %u %x", Child->getBlockID(), (unsigned)Child); 123 | *pChild = *Child->succ_begin(); 124 | continue; 125 | } 126 | // B's only successor is Child, Child's only predecessor is B, merge 127 | /* 128 | if(B->succ_size() == 1 && Child->pred_size() == 1) { 129 | DPRINT("join blocks %u %u", B->getBlockID(), Child->getBlockID()); 130 | this->JoinBlocks(B, Child); 131 | continue; 132 | } 133 | */ 134 | } 135 | DPRINT("dump modified cfgblock"); 136 | B->dump(G, resMgr.getCompilerInstance().getLangOpts()); 137 | } 138 | 139 | return true; 140 | } 141 | 142 | bool CFGFlattener::isTransparentBlock(CFGBlock *B) { 143 | if(!B) { 144 | return false; 145 | } 146 | // this is Entry Block or Exit Block 147 | if(B == &B->getParent()->getEntry() || B == &B->getParent()->getExit()) { 148 | return false; 149 | } 150 | if(B->pred_size() > 1 || B->succ_size() > 1) { 151 | return false; 152 | } 153 | Stmt *Label = const_cast(B->getLabel()); 154 | if(Label && !isa(Label)) { 155 | return false; 156 | } 157 | if(!B->empty()) { 158 | DPRINT("Block size %u %x", B->size(), (unsigned)B); 159 | return false; 160 | } 161 | // this may be a continue/break/goto 162 | if(B->succ_size() == 1){ 163 | return true; 164 | } 165 | return false; 166 | } 167 | 168 | bool CFGFlattener::JoinBlocks(CFGBlock *Parent, CFGBlock *Child) { 169 | assert(Parent); 170 | if(!Child) { 171 | return true; 172 | } 173 | BumpVectorContext &C = Parent->getParent()->getBumpVectorContext(); 174 | 175 | /// either an instance of LabelStmt, SwitchCase or CXXCatchStmt. 176 | Stmt *Label = const_cast(Child->getLabel()); 177 | if(!Label){ 178 | for(CFGBlock::iterator I = Child->begin(), IEnd = Child->end(); 179 | I != IEnd; ++I) { 180 | CFGElement &E = *I; 181 | if (const CFGStmt *CS = E.getAs().getPointer()) { 182 | Parent->appendStmt(const_cast(CS->getStmt()), C); 183 | } else if (const CFGInitializer *IE = E.getAs().getPointer()) { 184 | Parent->appendInitializer(IE->getInitializer(), C); 185 | } else if (const CFGAutomaticObjDtor *DE = E.getAs().getPointer()){ 186 | Parent->appendAutomaticObjDtor(const_cast(DE->getVarDecl()), const_cast(DE->getTriggerStmt()), C); 187 | } else if (const CFGBaseDtor *BE = E.getAs().getPointer()) { 188 | Parent->appendBaseDtor(BE->getBaseSpecifier(), C); 189 | } else if (const CFGMemberDtor *ME = E.getAs().getPointer()) { 190 | Parent->appendMemberDtor(const_cast(ME->getFieldDecl()), C); 191 | } else if (const CFGTemporaryDtor *TE = E.getAs().getPointer()) { 192 | Parent->appendTemporaryDtor(const_cast(TE->getBindTemporaryExpr()), C); 193 | } else { 194 | // FIXME: unhandled new type 195 | assert(false && "Unhandled CFGElement type"); 196 | } 197 | } 198 | } else if(isa(Label) || isa(Label)) { 199 | Parent->appendStmt(Label, C); 200 | } else if(isa(Label)) { 201 | return false; 202 | } 203 | //CFGTemporaryDtor T = Child->getTerminator(); 204 | Stmt *TC = Child->getTerminatorCondition(); 205 | Parent->setTerminator(TC); 206 | return true; 207 | } 208 | 209 | CaseStmt* CFGFlattener::CreateCaseStmt(CFGFlattener::GraphNodeInfo *N, clang::VarDecl *VD) { 210 | DPRINT("create case for node %d %x", N->NodeID, (unsigned)N->BindedCFGBlock); 211 | GraphInfo *G = N->getParent(); 212 | assert(G && "GraphNode not correctly binded to a Graph"); 213 | if(G->isTransparentNode(N)) { 214 | DPRINT("Transparent Node skipped"); 215 | return NULL; 216 | } 217 | 218 | ASTContext &Ctx = resMgr.getCompilerInstance().getASTContext(); 219 | CaseStmt *stCase = new (Ctx) 220 | CaseStmt(CreateIntegerLiteralX(N->NodeID), NULL, 221 | SourceLocation(), SourceLocation(), SourceLocation()); 222 | StmtPtrSmallVector caseBody; 223 | 224 | Stmt* Label = N->MergedCFGBlockLabel; 225 | assert((!Label || isa(Label)) && "not supported label type"); 226 | // If this block is a Label, reset label's body to NullStmt 227 | if(Label) { 228 | LabelStmt *LS = dyn_cast(Label); 229 | LS->setSubStmt(AddNewNullStmt()); 230 | caseBody.push_back(LS); 231 | } 232 | 233 | // Go through TransparentSucc 234 | for(unsigned i = 0; i != N->Succs.size(); i++) { 235 | N->Succs[i] = G->getAndUpdateTransparentSucc(N->Succs[i]); 236 | } 237 | 238 | // Fill the case body with CFGStmts 239 | CFGBlock *BB = N->BindedCFGBlock; 240 | Stmt* stTerm = BB->getTerminator().getStmt(); 241 | Stmt* stTermCond = BB->getTerminatorCondition(); 242 | stTermCond->dumpPretty(Ctx); 243 | for(unsigned i = 0; i != N->MergedCFGElements.size(); ++i) { 244 | CFGElement *elem = N->MergedCFGElements[i]; 245 | DPRINT("add stmt #%d", i); 246 | if(const CFGStmt *CS = elem->getAs().getPointer()) { 247 | Stmt *T = const_cast(CS->getStmt()); 248 | //FIXME if the block has DeclStmt, then it must be the decls at the funtion's beginning. 249 | // This may be wrong. 250 | // Directly pass is rude and may lead to problems. 251 | if(isa(T)) { 252 | continue; 253 | } 254 | T->dumpPretty(Ctx); 255 | if(T == stTermCond) { 256 | //FIXME now only support if-else, but may be others such as switch, && || 257 | DPRINT("terminator cond stmt met: %s", stTerm->getStmtClassName()); 258 | switch(stTerm->getStmtClass()) { 259 | default: 260 | // FIXME Bad case: int a, b; if(a && (b%2 ==1 )) {} 261 | { 262 | DPRINT("[FIXME]unsupported CFGStmt %s %x", stTerm->getStmtClassName(), (unsigned)stTerm); 263 | stTerm->dump(); 264 | break; 265 | } 266 | case Stmt::IfStmtClass: // if-else terminator 267 | { 268 | assert(N->Succs.size() == 2 && "Conditional Terminator should be if-else and has exactly 2 succs."); 269 | // Build IfStmt 270 | IfStmt *stIf = new (Ctx) 271 | IfStmt(Ctx, SourceLocation(), NULL, dyn_cast(T), NULL); 272 | 273 | StmtPtrSmallVector thenBody, elseBody; 274 | Stmt *stThen = N->Succs[0] ? (Stmt*)BuildVarAssignExpr(VD, CreateIntegerLiteralX(N->Succs[0]->NodeID)) : AddNewNullStmt(); 275 | Stmt *stElse = N->Succs[1] ? (Stmt*)BuildVarAssignExpr(VD, CreateIntegerLiteralX(N->Succs[1]->NodeID)) : AddNewNullStmt(); 276 | thenBody.push_back(stThen); 277 | elseBody.push_back(stElse); 278 | 279 | stIf->setThen(StVecToCompound(&thenBody)); 280 | stIf->setElse(StVecToCompound(&elseBody)); 281 | 282 | caseBody.push_back(stIf); 283 | stIf->dump(); 284 | break; 285 | } 286 | case Stmt::BinaryOperatorClass: // && || 287 | { 288 | DPRINT("Terminated by BinaryOperator:"); 289 | BinaryOperator *BO = dyn_cast(stTerm); 290 | BO->getLHS()->dump(); 291 | BO->getRHS()->dump(); 292 | DPRINT("Built IfStmt:"); 293 | // Build IfStmt 294 | IfStmt *stIf = new (Ctx) 295 | IfStmt(Ctx, SourceLocation(), NULL, dyn_cast(BO->getLHS()), NULL); 296 | StmtPtrSmallVector thenBody, elseBody; 297 | Stmt *stThen = N->Succs[0] ? (Stmt*)BuildVarAssignExpr(VD, CreateIntegerLiteralX(N->Succs[0]->NodeID)) : AddNewNullStmt(); 298 | Stmt *stElse = N->Succs[1] ? (Stmt*)BuildVarAssignExpr(VD, CreateIntegerLiteralX(N->Succs[1]->NodeID)) : AddNewNullStmt(); 299 | thenBody.push_back(stThen); 300 | elseBody.push_back(stElse); 301 | 302 | stIf->setThen(StVecToCompound(&thenBody)); 303 | stIf->setElse(StVecToCompound(&elseBody)); 304 | 305 | caseBody.push_back(stIf); 306 | stIf->dump(); 307 | break; 308 | } 309 | case Stmt::IndirectGotoStmtClass: 310 | { 311 | IndirectGotoStmt *IGS = dyn_cast(stTerm); 312 | caseBody.push_back(IGS); 313 | break; 314 | } 315 | } 316 | } else { 317 | // normal stmt 318 | caseBody.push_back(T); 319 | } 320 | } 321 | } 322 | // no terminator or terminator is a handled stmt. 323 | if(stTermCond == NULL || N->getParent()->Helper->handledStmt(stTermCond)) { 324 | if(GraphNodeInfo *succ = N->getFirstSucc()) { 325 | caseBody.push_back(BuildVarAssignExpr(VD, CreateIntegerLiteralX(succ->NodeID))); 326 | } 327 | } 328 | // add break 329 | BreakStmt *BS = new (Ctx) 330 | BreakStmt(SourceLocation()); 331 | caseBody.push_back(BS); 332 | 333 | stCase->setSubStmt(StVecToCompound(&caseBody)); 334 | stCase->dump(); 335 | 336 | return stCase; 337 | } 338 | 339 | 340 | bool CFGFlattener::GraphInfo::rebind(CFG *G, Stmt *Root) { 341 | clear(); 342 | if(!G) 343 | return true; 344 | 345 | cfgRoot = Root; 346 | NumBlockIDs = 0; 347 | Nodes.resize(G->size()); 348 | BlkIDMap.clear(); 349 | CFGBlock *Entry = &G->getEntry(), *Exit = &G->getExit(); 350 | 351 | // create id for each CFGBlock. 352 | // init GraphNode 353 | for(CFG::iterator I = G->begin(), IEnd = G->end(); 354 | I != IEnd; ++I, ++NumBlockIDs) { 355 | CFGBlock *B = *I; 356 | GraphNodeInfo &N = Nodes[NumBlockIDs]; 357 | N.clear(); 358 | N.setHeaderInfo(this, B, NumBlockIDs, &N); 359 | BlkIDMap[B] = NumBlockIDs; 360 | } 361 | // fill CFGBlock's info to corresponding GraphNode 362 | ASTContext &Ctx = flattener.resMgr.getCompilerInstance().getASTContext(); 363 | const LangOptions &LO = Ctx.getLangOpts(); 364 | // Decide the duplicate stmts and ignore them. 365 | Helper.reset(new GraphStmtHandleHelper(G, Root, LO)); 366 | 367 | for(unsigned i = 0; i < NumBlockIDs; ++i) { 368 | GraphNodeInfo &N = Nodes[i]; 369 | CFGBlock *B = N.BindedCFGBlock; 370 | // Node info 371 | N.MergedCFGBlocks.push_back(B); 372 | N.MergedCFGBlockLabel = B->getLabel(); 373 | N.MergedLoopTarkget = const_cast(B->getLoopTarget()); 374 | N.MergedCFGTerminator = B->getTerminator(); 375 | if(B == Entry) 376 | EntryNode = &N; 377 | if(B == Exit) 378 | ExitNode = &N; 379 | 380 | // add stmt elements of a CFGBlock 381 | unsigned StmtID = 1; 382 | for(CFGBlock::iterator I = B->begin(), IEnd = B->end(); 383 | I != IEnd; ++I, ++StmtID) { 384 | if(const CFGStmt *CS = I->getAs().getPointer()) { 385 | Stmt *T = const_cast(CS->getStmt()); 386 | // only add the last copy of the same Stmt 387 | Helper->setBlockID(B->getBlockID()); 388 | Helper->setStmtID(StmtID); 389 | if(!Helper->handledStmt(T)) { 390 | N.MergedCFGElements.push_back(&(*I)); 391 | } else { 392 | std::pair rootStmtID = Helper->getRootStmtID(T); 393 | DPRINT("Pass handledStmt [B%d.%d], Root is [B%d.%d]", 394 | B->getBlockID(), StmtID, 395 | rootStmtID.first, rootStmtID.second); 396 | } 397 | } 398 | } 399 | 400 | // add Out Edges 401 | for(CFGBlock::succ_iterator SI = B->succ_begin(), SIEnd = B->succ_end(); 402 | SI != SIEnd; ++SI) { 403 | unsigned idx = BlkIDMap[*SI]; 404 | DPRINT("edge %u -> %u", i, idx); 405 | N.Succs.push_back(&Nodes[idx]); 406 | ++N.OutDegree; 407 | ++Nodes[idx].InDegree; 408 | } 409 | } 410 | 411 | return true; 412 | } 413 | 414 | bool CFGFlattener::GraphInfo::isTransparentNode(GraphNodeInfo *N) { 415 | if(NULL == N) { 416 | return false; 417 | } 418 | if(N->MergedCFGBlockLabel) { 419 | return false; 420 | } 421 | // FIXME debug 422 | //return false; 423 | return N->MergedCFGElements.size() == 0 && (!N->MergedCFGTerminator); 424 | } 425 | 426 | // Disjoint Sets Union 427 | CFGFlattener::GraphNodeInfo* CFGFlattener::GraphInfo::getAndUpdateTransparentSucc(GraphNodeInfo* N) { 428 | if(N == NULL) { 429 | return NULL; 430 | } 431 | if(N->TransparentSucc != N) { 432 | return N->TransparentSucc = getAndUpdateTransparentSucc(N->TransparentSucc); 433 | } else if(isTransparentNode(N)) { 434 | return N->TransparentSucc = (N->Succs.size() > 0 ? N->Succs[0] : NULL); 435 | } else { 436 | return N; 437 | } 438 | } 439 | 440 | 441 | -------------------------------------------------------------------------------- /src/alg/FlattenCFG/CFGFlattener.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_ALT_FLATTENCFG_CFGFLATTENER_H 2 | #define OBFS_ALT_FLATTENCFG_CFGFLATTENER_H 3 | 4 | #include "alg/Algorithm.h" 5 | #include "clang/Analysis/CFG.h" 6 | #include "llvm/ADT/OwningPtr.h" 7 | #include "llvm/ADT/DenseMap.h" 8 | #include "llvm/ADT/SmallVector.h" 9 | 10 | using clang::Decl; 11 | using clang::Stmt; 12 | using clang::CFG; 13 | using clang::CFGBlock; 14 | using llvm::OwningPtr; 15 | using llvm::SmallVector; 16 | using llvm::DenseMap; 17 | 18 | class GraphStmtHandleHelper; 19 | class CFGFlattener; 20 | 21 | class GraphStmtHandleHelper { 22 | typedef llvm::DenseMap > StmtMapTy; // 23 | StmtMapTy StmtMap; 24 | Stmt *rootStmt; 25 | signed currentBlock; 26 | unsigned currentStmt; 27 | const LangOptions &LangOpts; 28 | 29 | class StmtMarker: public ASTTraverserPlus { 30 | StmtMapTy &stMap; 31 | Stmt *currentRoot; 32 | public: 33 | StmtMarker(StmtMapTy &M) 34 | : stMap(M), currentRoot(NULL) 35 | {} 36 | 37 | void UpdateMap(Stmt *S) { 38 | currentRoot = NULL; 39 | TraverseStmt(S); 40 | } 41 | 42 | bool VisitStmt(Stmt *S) { 43 | if(stMap.find(S) != stMap.end()) { 44 | if(currentRoot == NULL){ 45 | currentRoot = S; 46 | } else { 47 | stMap[S] = stMap[currentRoot]; 48 | } 49 | } 50 | return true; 51 | } 52 | 53 | bool ExitStmt(Stmt *S) { 54 | if(S == currentRoot) { 55 | currentRoot = NULL; 56 | } 57 | return true; 58 | } 59 | 60 | }; 61 | 62 | public: 63 | GraphStmtHandleHelper(const CFG* cfg, Stmt *Root, const LangOptions &LO) 64 | : currentBlock(0), currentStmt(0), rootStmt(Root), LangOpts(LO) 65 | { 66 | StmtMap.clear(); 67 | // Iterate over all CFGBlocks 68 | for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { 69 | unsigned j = 1; 70 | // Iterate over all Stmts in a CFGBlock 71 | for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ; 72 | BI != BEnd; ++BI, ++j ) { 73 | if (const CFGStmt *SE = BI->getAs().getPointer()) { 74 | // Remember that 'stmt' is the jth stmt of block I 75 | Stmt *stmt= const_cast(SE->getStmt()); 76 | std::pair P((*I)->getBlockID(), j); 77 | StmtMap[stmt] = P; 78 | } // end if const CFGStmt*... 79 | } // end for CFGBlock.const_iterator... 80 | } // end for CFG.const_iterator... 81 | StmtMarker(StmtMap).UpdateMap(rootStmt); 82 | } // end GraphStmtHandleHelper(... 83 | 84 | const LangOptions &getLangOpts() const { return LangOpts; } 85 | void setBlockID(signed i) { currentBlock = i; } 86 | void setStmtID(unsigned i) { currentStmt = i; } 87 | 88 | bool handledStmt(Stmt *S) { 89 | StmtMapTy::iterator I = StmtMap.find(S); 90 | if (I == StmtMap.end()) 91 | return false; 92 | if (currentBlock >= 0 && currentBlock == I->second.first 93 | && currentStmt == I->second.second) 94 | return false; 95 | return true; 96 | } 97 | 98 | std::pair getRootStmtID(Stmt *S) { 99 | StmtMapTy::iterator I = StmtMap.find(S); 100 | if (I == StmtMap.end()) 101 | return std::make_pair(-1,-1); 102 | else 103 | return I->second; 104 | } 105 | }; // end class GraphStmtPrinterHelper 106 | 107 | 108 | class CFGFlattener: public Algorithm { 109 | protected: 110 | class GraphNodeInfo; 111 | class GraphInfo; 112 | 113 | typedef SmallVector GraphNodeListTy; 114 | typedef SmallVector GraphNodePtrListTy; 115 | typedef SmallVector CFGBlockListTy; 116 | typedef SmallVector CFGElementListTy; 117 | 118 | // Node type of new graph type. 119 | class GraphNodeInfo { 120 | public: 121 | CFGBlock* BindedCFGBlock; 122 | unsigned NodeID; 123 | GraphInfo* Parent; 124 | 125 | // Help info for optmization 126 | GraphNodePtrListTy Preds; // FIXME not set or used 127 | GraphNodePtrListTy Succs; 128 | unsigned InDegree; 129 | unsigned OutDegree; 130 | GraphNodeInfo* TransparentSucc; 131 | 132 | // New node content after optimization 133 | CFGBlockListTy MergedCFGBlocks; 134 | CFGElementListTy MergedCFGElements; 135 | Stmt* MergedCFGBlockLabel; 136 | CFGTerminator MergedCFGTerminator; 137 | Stmt* MergedLoopTarkget; 138 | 139 | bool removePred(GraphNodeInfo *N); 140 | bool removeSucc(GraphNodeInfo *N); 141 | bool addPred(GraphNodeInfo *N); 142 | bool addSucc(GraphNodeInfo *N); 143 | 144 | GraphNodeInfo* getFirstSucc() { return Succs.size()>0 ? Succs[0] : NULL; } 145 | 146 | void setHeaderInfo(GraphInfo *P, CFGBlock *B, unsigned ID, GraphNodeInfo *TS) { 147 | Parent = P; 148 | BindedCFGBlock = B; 149 | NodeID = ID; 150 | TransparentSucc = TS; 151 | } 152 | 153 | GraphInfo* getParent(){ return Parent; } 154 | 155 | bool clear() { 156 | Preds.clear(); 157 | Succs.clear(); 158 | InDegree = OutDegree = 0; 159 | TransparentSucc = NULL; 160 | MergedCFGBlocks.clear(); 161 | MergedCFGElements.clear(); 162 | NodeID = 0; 163 | Parent = NULL; 164 | } 165 | }; 166 | 167 | // New control flow graph type. Each node is a "Case" after transformed. 168 | class GraphInfo { 169 | CFGFlattener &flattener; 170 | public: 171 | CFG* BindedCFG; 172 | Stmt *cfgRoot; 173 | OwningPtr Helper; 174 | 175 | DenseMap BlkIDMap; 176 | 177 | GraphNodeListTy Nodes; 178 | GraphNodeInfo* EntryNode; 179 | GraphNodeInfo* ExitNode; 180 | 181 | unsigned NumBlockIDs; 182 | 183 | GraphInfo(CFGFlattener &F, CFG *G = NULL, Stmt *R = NULL) 184 | : flattener(F), BindedCFG(0), cfgRoot(0) { 185 | if(G != NULL) { 186 | rebind(G, R); 187 | } 188 | } 189 | 190 | bool clear() { 191 | BindedCFG = NULL; 192 | cfgRoot = NULL; 193 | Nodes.clear(); 194 | EntryNode = ExitNode = NULL; 195 | NumBlockIDs = 0; 196 | return true; 197 | } 198 | 199 | bool rebind(CFG* G, Stmt *Root); 200 | 201 | bool isTransparentNode(GraphNodeInfo* N); 202 | 203 | GraphNodeInfo* getAndUpdateTransparentSucc(GraphNodeInfo* N); 204 | }; 205 | 206 | OwningPtr cfgraph; 207 | GraphInfo newgraph; 208 | 209 | // Remove goto stmt 210 | // join nodes that should belong to the same Case 211 | bool PrepareGraph(CFG *G); 212 | 213 | bool isTransparentBlock(CFGBlock *B); 214 | bool JoinBlocks(CFGBlock *Parent, CFGBlock *Child); 215 | 216 | // Do flattening, transform to while-switch body 217 | // VD: switch variable decl 218 | // TODO Add merged nodes support 219 | CaseStmt* CreateCaseStmt(GraphNodeInfo *N, VarDecl *VD); 220 | 221 | public: 222 | CFGFlattener(ResourceManager &RM) 223 | : Algorithm(RM), 224 | newgraph(*this) 225 | {} 226 | 227 | bool HandleDecl(Decl *D); 228 | }; 229 | 230 | #endif 231 | -------------------------------------------------------------------------------- /src/alg/FlattenCFG/FlattenCFGTransformer.cpp: -------------------------------------------------------------------------------- 1 | #include "alg/FlattenCFG/FlattenCFGTransformer.h" 2 | #include "alg/FlattenCFG/VarRenamer.h" 3 | #include "alg/FlattenCFG/StmtPretransformer.h" 4 | #include "alg/FlattenCFG/LocalDeclMover.h" 5 | #include "alg/FlattenCFG/CFGFlattener.h" 6 | #include "llvm/ADT/OwningPtr.h" 7 | using namespace clang; 8 | 9 | using llvm::OwningPtr; 10 | 11 | bool FlattenCFGTransformer::execute() { 12 | this->renamer = new VarRenamer(this->resMgr); 13 | this->preTranser = new StmtPretransformer(this->resMgr); 14 | OwningPtr refMap(new RefVarToPtrMap(0)); 15 | assert(refMap.get() && "reference variable map alloc failed"); 16 | this->dclMover = new LocalDeclMover(this->resMgr, refMap.get()); 17 | this->flat = new CFGFlattener(this->resMgr); 18 | 19 | TranslationUnitDecl *decls = this->resMgr.getCompilerInstance().getASTContext().getTranslationUnitDecl(); 20 | for(TranslationUnitDecl::decl_iterator I = decls->decls_begin(), E = decls->decls_end(); 21 | I != E; ++I) { 22 | Decl *D = *I; 23 | DPRINT("TUDecl %s %x | Ctx %x -> p %x", D->getDeclKindName(), (unsigned int)D, (unsigned int)D->getDeclContext(), (unsigned int)decls); 24 | SourceLocation Loc = D->getLocation(); 25 | 26 | if(Loc.isInvalid() 27 | || this->compInst.getSourceManager().isInSystemHeader(Loc)){ 28 | continue; 29 | } 30 | 31 | if(HandleAnyFunctionDecl(D)) { 32 | continue; 33 | } else if(HandleAnyClassDecl(D)) { 34 | continue; 35 | } 36 | } 37 | 38 | delete this->renamer; 39 | delete this->preTranser; 40 | delete this->dclMover; 41 | delete this->flat; 42 | refMap.reset(); 43 | 44 | return true; 45 | } 46 | 47 | bool FlattenCFGTransformer::HandleAnyFunctionDecl(Decl *D){ 48 | DPRINT("enter FuncDecl"); 49 | FunctionDecl *fd = NULL; 50 | if(FunctionTemplateDecl *td = dyn_cast(D)) { // function template 51 | fd = td->getTemplatedDecl(); 52 | } else if(FunctionDecl *td = dyn_cast(D)) { // function, c++ method 53 | fd = td; 54 | } else { 55 | DPRINT("unknown FunctionDecl type: %s %x", D->getDeclKindName(),(unsigned int)D); 56 | return false; 57 | } 58 | assert(fd && "get FunctionDecl failed"); 59 | 60 | //TODO 61 | Stmt *oldBody = fd->getBody(); 62 | this->renamer->HandleDecl(fd); 63 | this->preTranser->HandleDecl(fd); 64 | this->dclMover->HandelDecl(fd); 65 | this->flat->HandleDecl(fd); 66 | 67 | // refresh RewriteBuffer 68 | Rewriter &rw = resMgr.getRewriter(); 69 | rw.ReplaceStmt(oldBody, fd->getBody()); 70 | 71 | return true; 72 | } 73 | 74 | bool FlattenCFGTransformer::HandleAnyClassDecl(Decl *D) { 75 | DPRINT("enter ClassDecl"); 76 | CXXRecordDecl *cd = NULL; 77 | if(ClassTemplateDecl *td = dyn_cast(D)) { // class template 78 | cd = td->getTemplatedDecl(); 79 | } else if(CXXRecordDecl *td = dyn_cast(D)) { // class 80 | cd = td; 81 | } else { 82 | DPRINT("not class type Decl"); 83 | return false; 84 | } 85 | 86 | assert(cd && "get CXXRecordDecl failed"); 87 | 88 | // process all member methods 89 | for(CXXRecordDecl::method_iterator I = cd->method_begin(), E = cd->method_end(); 90 | I != E; ++I){ 91 | HandleAnyFunctionDecl(*I); 92 | } 93 | return true; 94 | } 95 | 96 | -------------------------------------------------------------------------------- /src/alg/FlattenCFG/FlattenCFGTransformer.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_ALG_FlattenCFG_FlattenCFGTransformer_H 2 | #define OBFS_ALG_FlattenCFG_FlattenCFGTransformer_H 3 | 4 | #include "alg/Algorithm.h" 5 | #include "alg/FlattenCFG/VarRenamer.h" 6 | #include "alg/FlattenCFG/StmtPretransformer.h" 7 | #include "alg/FlattenCFG/LocalDeclMover.h" 8 | #include "alg/FlattenCFG/CFGFlattener.h" 9 | using namespace clang; 10 | 11 | class FlattenCFGTransformer; 12 | 13 | class FlattenCFGTransformer : public Algorithm { 14 | public: 15 | FlattenCFGTransformer(ResourceManager &RM) 16 | : Algorithm(RM) 17 | {} 18 | 19 | virtual bool execute(); 20 | 21 | protected: 22 | VarRenamer *renamer; 23 | StmtPretransformer *preTranser; 24 | LocalDeclMover *dclMover; 25 | CFGFlattener *flat; 26 | 27 | bool HandleTopLevelDecl(DeclGroupRef D); 28 | bool HandleAnyFunctionDecl(Decl *D); 29 | bool HandleAnyClassDecl(Decl *D); 30 | 31 | }; 32 | 33 | 34 | 35 | #endif 36 | 37 | -------------------------------------------------------------------------------- /src/alg/FlattenCFG/LocalDeclMover.cpp: -------------------------------------------------------------------------------- 1 | #include "alg/FlattenCFG/LocalDeclMover.h" 2 | using namespace clang; 3 | 4 | bool LocalDeclMover::HandelDecl(Decl *D) { 5 | DPRINT("START LocalDeclMover"); 6 | if(!D){ 7 | return true; 8 | } 9 | D->dump(); 10 | Stmt *body = D->getBody(); 11 | 12 | this->rootStack.clear(); 13 | this->topDeclStmts.clear(); 14 | 15 | Stmt *vRoot = AddNewNullStmt(); 16 | this->parMap.reset(new ParentMap(vRoot)); 17 | assert(this->refMap && "ref var map should not be null"); 18 | 19 | this->TraverseDecl(D); 20 | 21 | this->rootStack.clear(); 22 | this->topDeclStmts.clear(); 23 | this->parMap.reset(); 24 | 25 | DeallocateStmt(vRoot); 26 | 27 | DPRINT("END LocalDeclMover"); 28 | D->dump(); 29 | return true; 30 | } 31 | 32 | bool LocalDeclMover::VisitStmt(Stmt *S) { 33 | if(!S) { 34 | return true; 35 | } 36 | // add root stmt for: 37 | // CompoundStmt 38 | if(!this->parMap->hasParent(S)) { 39 | this->parMap->addStmt(S); 40 | if(isa(S)) { 41 | this->rootStack.push_back(S); 42 | this->topDeclStmts.push_back(StmtPtrSmallVector()); 43 | } 44 | } 45 | 46 | //Sema &Sm = this->resMgr.getCompilerInstance().getSema(); 47 | ASTContext &Ctx = this->resMgr.getCompilerInstance().getASTContext(); 48 | DPRINT("Stmt %s ( %x -> p %x )", S->getStmtClassName(), (unsigned int)S, (unsigned int)(this->parMap->getParent(S))); 49 | #ifdef DEBUG 50 | S->dump(), S->dumpPretty(Ctx); 51 | #endif 52 | 53 | switch(S->getStmtClass()) { 54 | case Stmt::NoStmtClass: 55 | case Stmt::WhileStmtClass: 56 | case Stmt::DoStmtClass: 57 | case Stmt::ForStmtClass: 58 | case Stmt::CXXTryStmtClass: 59 | case Stmt::CXXCatchStmtClass: 60 | DPRINT("skip atom"); 61 | return true; 62 | 63 | //FIXME move to StmtPretransformer 64 | // case Stmt::IfStmtClass: 65 | // //cond var decl transform, to avoid dumpPretty bug 66 | // this->ExtractIfCondVarDecl(dyn_cast(S)); 67 | // break; 68 | 69 | case Stmt::DeclRefExprClass: 70 | { 71 | // only transform LocaVarDecl ref to ptr type 72 | DeclRefExpr *E = dyn_cast(S); 73 | if(VarDecl *VD = dyn_cast_or_null(E->getDecl())) { 74 | if(VD->isLocalVarDecl() && 75 | VD->getType()->isReferenceType()) { 76 | DPRINT("DeclRefExpr of LocalVarDecl met"); 77 | this->replaceChild(this->parMap->getParent(S), S, 78 | this->RefExprToPtrExpr(E)); 79 | } 80 | } 81 | } 82 | break; 83 | 84 | case Stmt::DeclStmtClass: 85 | { 86 | //moved to ExitStmt 87 | //this->WorkOnDeclStmt(dyn_cast(S)); 88 | } 89 | break; 90 | } 91 | 92 | return true; 93 | } 94 | 95 | 96 | bool LocalDeclMover::ExitStmt(Stmt *S) { 97 | if(!S) { 98 | return true; 99 | } 100 | 101 | //do declstmt transform 102 | if(DeclStmt *DS = dyn_cast(S)) { 103 | this->WorkOnDeclStmt(DS); 104 | } 105 | 106 | // update with new stmtbody 107 | if(this->rootStack.back() == S) { 108 | StmtPtrSmallVector &newBody = this->topDeclStmts.back(); 109 | DPRINT("root stmt type %s %x | children size %d", S->getStmtClassName(), (unsigned int)S, newBody.size()); 110 | if(newBody.size() > 0) { 111 | if(!isa(S)) { 112 | DPRINT("unexpected stmt type %s %x", S->getStmtClassName(), (unsigned int)S); 113 | assert(false); 114 | } 115 | newBody.insert(newBody.end(), S->child_begin(), S->child_end()); 116 | //FIXME: only compound 117 | updateChildrenStmts(S, RemoveNullStmtInVector(&newBody)); 118 | } 119 | 120 | this->topDeclStmts.pop_back(); 121 | this->rootStack.pop_back(); 122 | } 123 | return true; 124 | } 125 | 126 | Expr* LocalDeclMover::BuildAssignExprWithTypeCast(Expr *LHS, Expr *RHS) { 127 | assert(LHS && "left-hand stmt shouldn't be null"); 128 | ASTContext &Ctx = this->resMgr.getCompilerInstance().getASTContext(); 129 | QualType realTy = LHS->getType().getDesugaredType(Ctx); 130 | //add explicit type cast "Type()" for struct or class 131 | //FIXME: any more cases? 132 | if(realTy->isStructureOrClassType()) { 133 | //FIXME: any more cases? 134 | if(!RHS || 135 | isa(RHS) && dyn_cast(RHS)->getNumArgs() == 0) { 136 | //if expr's type is the same as var, don't add cast (newInit->getType()) 137 | DPRINT("construct(void)"); 138 | RHS = BuildTempObjectConstuctExpr(realTy, NULL); 139 | } else { 140 | DPRINT("construct(not void)"); 141 | RHS = BuildTempObjectConstuctExpr(realTy, RHS); 142 | } 143 | } 144 | 145 | assert(RHS); 146 | return BuildCommonAssignExpr(LHS, RHS); 147 | } 148 | 149 | Expr* LocalDeclMover::BuildAssignExprWithTypeCast(VarDecl *D, Expr *RHS) { 150 | return this->BuildAssignExprWithTypeCast(BuildVarDeclRefExpr(D), RHS); 151 | } 152 | 153 | bool LocalDeclMover::ExtractIfCondVarDecl(IfStmt *S) { 154 | if(!S) { 155 | return false; 156 | } 157 | ASTContext &Ctx = this->resMgr.getCompilerInstance().getASTContext(); 158 | if(DeclStmt *stIfDcl = const_cast(S->getConditionVariableDeclStmt())) { 159 | Stmt *Parent = this->parMap->getParent(S); 160 | assert(Parent && "IfStmt should have a parent"); 161 | S->setConditionVariable(Ctx, NULL); 162 | 163 | StmtPtrSmallVector *compBody = new StmtPtrSmallVector(); 164 | compBody->push_back(stIfDcl); 165 | compBody->push_back(S); 166 | CompoundStmt *newStmt = StVecToCompound(compBody); 167 | delete compBody; 168 | 169 | this->replaceChild(Parent, S, newStmt); 170 | this->parMap->addStmt(Parent); 171 | } 172 | return true; 173 | } 174 | 175 | 176 | bool LocalDeclMover::WorkOnDeclStmt(DeclStmt *DS) { 177 | DPRINT("WorkOnDeclStmt"); 178 | ASTContext &Ctx = resMgr.getCompilerInstance().getASTContext(); 179 | DeclGroupRef DG = DS->getDeclGroup(); 180 | StmtPtrSmallVector vecAssign; 181 | StmtPtrSmallVector::iterator curPos = vecAssign.end(); 182 | for(DeclGroupRef::iterator I = DG.begin(), IEnd = DG.end(); 183 | I != IEnd; ++I) { 184 | Decl *D = *I; 185 | if(VarDecl *VD = dyn_cast(D)) { 186 | // only CompoundStmt/Expr/NULL returned 187 | // arrayType returns CompoundStmt 188 | // other vars return Expr 189 | // if no initList, return NULL 190 | Stmt *stAssign = this->WorkOnAVarDecl(VD); 191 | if(stAssign){ 192 | if(CompoundStmt *stCpd = dyn_cast(stAssign)) { 193 | vecAssign.insert(vecAssign.end(), stCpd->child_begin(), stCpd->child_end()); 194 | curPos = vecAssign.end(); 195 | } else if(Expr *exprVarAssign = dyn_cast(stAssign)) { 196 | if(curPos == vecAssign.end()){ 197 | vecAssign.push_back(stAssign); 198 | } else { 199 | assert(isa(*curPos) && "Last stmt is not a expr"); 200 | *curPos = this->BuildCommaExpr(dyn_cast(*curPos), exprVarAssign); 201 | } 202 | curPos = vecAssign.end()-1; 203 | } else { 204 | DPRINT("return type error"); 205 | } 206 | } 207 | } else if(TagDecl *TD = dyn_cast(D)) { 208 | this->WorkOnATagDecl(TD); 209 | } else { 210 | DPRINT("unhandled declstmt: %s %x", D->getDeclKindName(), (unsigned int)D); 211 | } 212 | } 213 | 214 | Stmt *Parent = parMap->getParent(DS); 215 | Stmt *assignBlock = vecAssign.size() > 1 ? this->StVecToCompound(RemoveNullStmtInVector(&vecAssign)) 216 | : vecAssign.size() == 1 ? vecAssign.back() 217 | : NullChildStmt(Parent); 218 | // remove orignal DeclStmt with new assignment code block on the AST 219 | this->replaceChild(Parent, DS, assignBlock); 220 | this->parMap->addStmt(assignBlock); 221 | 222 | return true; 223 | } 224 | 225 | Stmt* LocalDeclMover::WorkOnAVarDecl(VarDecl *D) { 226 | DPRINT("Handle VarDecl %s %x | Ctx %x(%s) -> p %x", 227 | D->getNameAsString().c_str(), (unsigned int)D, 228 | (unsigned int)D->getDeclContext(), D->getDeclContext()->getDeclKindName(), 229 | (unsigned int)D->getDeclContext()->getParent()); 230 | ASTContext &Ctx = this->resMgr.getCompilerInstance().getASTContext(); 231 | //anoyomous 232 | if(!D->getIdentifier()) { 233 | DPRINT("anoyomous var"); 234 | return NULL; 235 | } 236 | //not local var 237 | //FIXME var created by Algorithm::CreateVar() can't pass the test 238 | // if(!D->isLocalVarDecl()) { 239 | // DPRINT("not local or parmVar"); 240 | // return NULL; 241 | // } 242 | //extern 243 | if(D->hasExternalStorage()) { 244 | DPRINT("extern skipped"); 245 | return NULL; 246 | } 247 | //static, not supported. 248 | if(D->isStaticLocal()) { 249 | assert(false && "static local variable not supported yet."); 250 | return NULL; 251 | } 252 | QualType Ty = D->getType(); 253 | QualType realTy = Ty.getDesugaredType(Ctx); 254 | DPRINT("QualType "); 255 | #ifdef DEBUG 256 | realTy->dump(); 257 | #endif 258 | 259 | Stmt *retAssign = NULL; 260 | 261 | //remove const qualifier 262 | if(realTy.isConstQualified()) { 263 | DPRINT("const-qualified"); 264 | realTy.removeLocalConst(); 265 | D->setType(realTy); 266 | } 267 | 268 | Expr *IE = D->getInit(); 269 | VarDecl *newVD = NULL; 270 | Expr *newInit = NULL; 271 | 272 | if(realTy->isReferenceType()) { 273 | //reference type, only transform LocalVarDecl 274 | if(D->isLocalVarDecl()){ 275 | newVD = this->RefToPtrType(D); 276 | if(IE) { 277 | newInit = this->BuildUnaryOperator( 278 | this->BuildParenExpr(IE), 279 | clang::UO_AddrOf); 280 | } 281 | } else { 282 | DPRINT("reference type not LocalVar"); 283 | return NULL; 284 | } 285 | } else { 286 | newInit = D->getInit(); 287 | newVD = D; 288 | newVD->setInit(NULL); 289 | } 290 | 291 | //if has InitList, construct assign expr 292 | if(newInit) { 293 | #ifdef DEBUG 294 | newInit->dump(); 295 | #endif 296 | if(realTy->isArrayType()) { //ArrayType 297 | DPRINT("ArrayType"); 298 | // go down to reach the underlying InitListExpr 299 | while(ExprWithCleanups *cleanup = dyn_cast(newInit)) { 300 | newInit = cleanup->getSubExpr(); 301 | } 302 | assert(isa(newInit) && "Array's init list should be a list"); 303 | retAssign = this->CreateArrayInitListAssignStmt(newVD, dyn_cast(newInit)); 304 | } else { 305 | DPRINT("Expr type: lhs %x, rhs %x", 306 | realTy.getTypePtr(), newInit->getType().getDesugaredType(Ctx).getTypePtr()); 307 | retAssign = this->BuildAssignExprWithTypeCast(newVD, newInit); 308 | assert(retAssign); 309 | DPRINT("retAssign"); 310 | retAssign->dump(); 311 | } 312 | } 313 | 314 | assert(!this->topDeclStmts.empty() && "topDeclStmts vec null, maybe no root stmt detected?"); 315 | StmtPtrSmallVector &topDs = this->topDeclStmts.back(); 316 | Stmt *stNewDcl = this->BuildDeclStmt(newVD); 317 | assert(stNewDcl != NULL && "build new declstmt failed"); 318 | topDs.push_back(stNewDcl); 319 | 320 | // If this not added, new init expr will not be visited or correctly updated 321 | parMap->addStmt(retAssign); 322 | return retAssign; 323 | } 324 | 325 | bool LocalDeclMover::WorkOnATagDecl(TagDecl *D) { 326 | //FIXME: implement 327 | // Caller ensures the incoming D is not a global decl, so no need to test here 328 | DPRINT("Handle TagDecl %x | Ctx %x -> p %x", (unsigned int)D, (unsigned int)D->getDeclContext(), (unsigned int)D->getDeclContext()->getParent()); 329 | ASTContext &Ctx = this->resMgr.getCompilerInstance().getASTContext(); 330 | StmtPtrSmallVector &topDs = this->topDeclStmts.back(); 331 | Stmt *stNewDcl = this->BuildDeclStmt(D); 332 | topDs.push_back(stNewDcl); 333 | return true; 334 | } 335 | 336 | Stmt* LocalDeclMover::CreateArrayInitListAssignStmt(VarDecl *D, InitListExpr *E) { 337 | //FIXME implement 338 | ASTContext &Ctx = resMgr.getCompilerInstance().getASTContext(); 339 | QualType Ty = D->getType().getDesugaredType(Ctx); 340 | assert(Ty->isArrayType() && "incoming VarDecl should be ArrayType"); 341 | 342 | DeclRefExpr *R = BuildVarDeclRefExpr(D); 343 | StmtPtrSmallVector vecAssign, vecIdx; 344 | this->DFSInitListExpr(E, R, &vecIdx, &vecAssign); 345 | 346 | return StVecToCompound(&vecAssign); 347 | } 348 | 349 | bool LocalDeclMover::DFSInitListExpr(Expr *E, DeclRefExpr *R, StmtPtrSmallVector *vIdx, StmtPtrSmallVector *vRes) { 350 | //FIXME implement 351 | if(!E) { 352 | return true; 353 | } 354 | ASTContext &Ctx = resMgr.getCompilerInstance().getASTContext(); 355 | if(InitListExpr *IL = dyn_cast(E)) { 356 | for(unsigned i = 0, iend = IL->getNumInits(); 357 | i != iend; ++i) { 358 | Expr *init = IL->getInit(i); 359 | vIdx->push_back(CreateIntegerLiteralX(i)); 360 | DFSInitListExpr(init, R, vIdx, vRes); 361 | Ctx.Deallocate(vIdx->pop_back_val()); 362 | } 363 | 364 | return true; 365 | } else { 366 | ExprResult eRes = BuildArraySubscriptExpr(R, (Expr**)&(*vIdx->begin()), vIdx->size()); 367 | assert(!eRes.isInvalid()); 368 | 369 | Expr* assign = this->BuildAssignExprWithTypeCast(eRes.get(), E); 370 | 371 | vRes->push_back(assign); 372 | return true; 373 | } 374 | 375 | assert(false); 376 | return false; 377 | } 378 | 379 | 380 | ParenExpr* LocalDeclMover::RefExprToPtrExpr(DeclRefExpr *E) { 381 | assert(E && "DeclRefExpr cannot be NULL"); 382 | ASTContext &Ctx = this->resMgr.getCompilerInstance().getASTContext(); 383 | VarDecl *DRef = dyn_cast_or_null(E->getDecl()); 384 | assert(DRef && "decl refered to is NULL or not VarDecl"); 385 | 386 | VarDecl *DPtr = this->RefToPtrType(DRef); 387 | 388 | DeclRefExpr *newDclRef = this->BuildVarDeclRefExpr(DPtr); 389 | 390 | Expr* DE = this->BuildUnaryOperator(newDclRef, clang::UO_Deref); 391 | 392 | ParenExpr *PE = new (Ctx) 393 | ParenExpr(SourceLocation(), SourceLocation(), DE); 394 | 395 | #ifdef DEBUG 396 | DPRINT("DeclRefExpr to PtrExpr replacement"); 397 | PE->dump(); 398 | #endif 399 | return PE; 400 | } 401 | 402 | VarDecl* LocalDeclMover::RefToPtrType(VarDecl *D) { 403 | assert(D && "VarDecl cannot be NULL"); 404 | ASTContext &Ctx = this->resMgr.getCompilerInstance().getASTContext(); 405 | QualType QT = D->getType().getDesugaredType(Ctx); 406 | assert(QT->isReferenceType() && "not a reference type"); 407 | 408 | RefVarToPtrMap::iterator I = refMap->find(D); 409 | if(I != refMap->end()) { 410 | return I->second; 411 | } 412 | //FIXME: need to remove 'reference' 413 | //getPointeeType() 414 | QualType PT = Ctx.getPointerType(QT->getPointeeType()).getDesugaredType(Ctx); 415 | DeclStmt *dclP = this->CreateVar(PT, D->getDeclContext()); 416 | VarDecl *Ptr = dyn_cast(dclP->getSingleDecl()); 417 | 418 | #ifdef DEBUG 419 | Ptr->dump(); 420 | #endif 421 | 422 | refMap->operator[](D) = Ptr; 423 | return Ptr; 424 | } 425 | -------------------------------------------------------------------------------- /src/alg/FlattenCFG/LocalDeclMover.h: -------------------------------------------------------------------------------- 1 | //not only a TopLevelDecl 2 | #ifndef OBFS_ALG_FLATTENCFG_LOCALDECLMOVER_H 3 | #define OBFS_ALG_FLATTENCFG_LOCALDECLMOVER_H 4 | 5 | #include "alg/Algorithm.h" 6 | #include "alg/FlattenCFG/ASTTraverserPlus.h" 7 | #include "ResourceManager.h" 8 | #include "clang/AST/ParentMap.h" 9 | #include "llvm/ADT/DenseMap.h" 10 | #include "llvm/ADT/OwningPtr.h" 11 | 12 | class LocalDeclMover; 13 | class DeclExtractor; 14 | class RefToPtrTranformer; 15 | 16 | using llvm::OwningPtr; 17 | using llvm::DenseMap; 18 | using namespace clang; 19 | 20 | typedef DenseMap RefVarToPtrMap; 21 | 22 | // This class moves all local variable/class/union/enum/struct/array decls 23 | // to the beginning of its function/method body, and change the init expr 24 | // to assign expr. 25 | class LocalDeclMover: public Algorithm, public ASTTraverserPlus { 26 | protected: 27 | typedef SmallVector StmtListVec; 28 | // store all root Stmt nodes by dfs order 29 | // assume all Stmts that have no parent are root. 30 | // assume only CompoundStmt can be root stmt. 31 | StmtPtrSmallVector rootStack; 32 | 33 | // temp store new top decl stmts of a root stmt 34 | StmtListVec topDeclStmts; 35 | 36 | OwningPtr parMap; 37 | RefVarToPtrMap *refMap; 38 | 39 | // create "LHS = RHS" or "LHS = LHSType(RHS)" 40 | // automatically detect whether casting is needed. 41 | Expr* BuildAssignExprWithTypeCast(Expr *LHS, Expr *RHS); 42 | // create "D = RHS" or "D = DType(RHS)" 43 | Expr* BuildAssignExprWithTypeCast(VarDecl *D, Expr *RHS); 44 | 45 | //extract vardecl in ifcond to avoid dumpPretty bug: 46 | //if(T t=x){..} to T t=x; if(t){..} 47 | bool ExtractIfCondVarDecl(IfStmt *S); 48 | 49 | bool WorkOnDeclStmt(DeclStmt *S); 50 | 51 | // Only returns CompoundStmt or Expr or NULL. 52 | Stmt* WorkOnAVarDecl(VarDecl *D); 53 | 54 | // The caller must ensure the incoming D is not global 55 | bool WorkOnATagDecl(TagDecl *D); 56 | 57 | Stmt* CreateArrayInitListAssignStmt(VarDecl *D, InitListExpr *E); 58 | 59 | // recursively visit an InitListExpr E (if it is) 60 | // build all assign op expr and store them in vRes 61 | // vIdx is for storing idx exprs during the DFS. 62 | // FIXME should be ExprPtrSmallVector 63 | bool DFSInitListExpr(Expr* E, DeclRefExpr *R, StmtPtrSmallVector *vIdx, StmtPtrSmallVector *vRes); 64 | 65 | ParenExpr* RefExprToPtrExpr(DeclRefExpr *E); 66 | VarDecl* RefToPtrType(VarDecl *D); 67 | 68 | bool addBeginningDeclStmt(VarDecl *D); 69 | public: 70 | LocalDeclMover(ResourceManager &RM, RefVarToPtrMap *RP) 71 | : Algorithm(RM), 72 | refMap(RP) 73 | {} 74 | 75 | bool HandelDecl(Decl *D); 76 | 77 | bool VisitStmt(Stmt *S); 78 | bool ExitStmt(Stmt *S); 79 | }; 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /src/alg/FlattenCFG/MoveLocalDeclToTop.h.bak: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_ALG_FLATTENCFG_MOVELOCALDECLTOTOP_H 2 | #define OBFS_ALG_FLATTENCFG_MOVELOCALDECLTOTOP_H 3 | 4 | #include "../Algorithm.h" 5 | //#include "FlattenCFGTransformer.h" 6 | #include "ASTTraverser.h" 7 | #include "StmtPretransformer.h" 8 | 9 | using namespace clang; 10 | 11 | class MoveLocalDeclToTop; 12 | class ExtractVarDecl; 13 | 14 | class MoveLocalDeclToTop: public Algorithm { 15 | public: 16 | friend class ExtractVarDecl; 17 | 18 | MoveLocalDeclToTop(ResourceManager &RM) 19 | : Algorithm(RM) 20 | {} 21 | 22 | bool HandelDecl(Decl *D); 23 | 24 | protected: 25 | 26 | }; 27 | 28 | // move variable declarations to the top of the function, 29 | // transform the original declaration to an assign operation 30 | class ExtractVarDecl: public ASTTraverser { 31 | public: 32 | friend class MoveLocalDeclToTop; 33 | 34 | ExtractVarDecl(MoveLocalDeclToTop &M, Stmt *R) 35 | : mover(M), 36 | topStmt(R), 37 | parMap(new ParentMap(R)), 38 | topDeclStmts(StmtPtrSmallVector()) 39 | {} 40 | 41 | TraverseCode VisitStmt(Stmt *S); 42 | 43 | protected: 44 | bool addBeginningDeclStmt(clang::VarDecl *D); 45 | 46 | MoveLocalDeclToTop &mover; 47 | Stmt *topStmt; 48 | StmtPtrSmallVector topDeclStmts; 49 | OwningPtr parMap; 50 | 51 | static int atomLevel; 52 | }; 53 | 54 | #endif 55 | -------------------------------------------------------------------------------- /src/alg/FlattenCFG/StmtPretransformer.cpp: -------------------------------------------------------------------------------- 1 | #include "alg/FlattenCFG/StmtPretransformer.h" 2 | #include "llvm/ADT/DenseMap.h" 3 | using namespace clang; 4 | 5 | bool StmtPretransformer::HandleDecl(Decl *D) { 6 | DPRINT("START StmtPretransformer"); 7 | assert(isa(D) && "not function decl"); 8 | 9 | if(!D->hasBody()){ 10 | DPRINT("no function body"); 11 | return true; 12 | } 13 | 14 | //TODO 15 | this->stmtStack.clear(); 16 | this->stmtMap.clear(); 17 | this->parMap = new ParentMap(D->getBody()); 18 | this->declStack.clear(); 19 | 20 | this->TraverseDecl(D); 21 | 22 | this->stmtStack.clear(); 23 | while(!stmtMap.empty()) { 24 | delete stmtMap.begin()->second; 25 | stmtMap.erase(stmtMap.begin()); 26 | } 27 | delete this->parMap; 28 | this->parMap = NULL; 29 | this->declStack.clear(); 30 | DPRINT("END StmtPretransformer"); 31 | 32 | return true; 33 | } 34 | 35 | 36 | bool StmtPretransformer::VisitDecl(Decl *D) { 37 | DPRINT("visitDecl %x(%s) Ctx %x", (unsigned)D, D->getDeclKindName(), (unsigned)D->getDeclContext()); 38 | if(isa(D)) { 39 | declStack.push_back(D); 40 | } 41 | return true; 42 | } 43 | 44 | bool StmtPretransformer::ExitDecl(Decl *D) { 45 | DPRINT("exitDecl"); 46 | if(isa(D)) { 47 | declStack.pop_back(); 48 | } 49 | return true; 50 | } 51 | 52 | bool StmtPretransformer::VisitStmt(Stmt *S) { 53 | //the *&S may change during the transform, 54 | //so we need to record S 55 | StmtPretransInfo *pInfo = new StmtPretransInfo(S, &S, NULL); 56 | stmtStack.push_back(pInfo); 57 | stmtMap[S] = pInfo; 58 | if(!this->parMap->getParent(S)) { 59 | this->parMap->addStmt(S); 60 | } 61 | 62 | DPRINT("push stmt %s %x %x %x", S->getStmtClassName(), (unsigned int)S, stmtStack.back(), stmtMap[S]); 63 | return true; 64 | } 65 | 66 | bool StmtPretransformer::ExitStmt(Stmt *S) { 67 | //TODO if is atom, don't go deeper 68 | 69 | //TODO 70 | DPRINT("leaving Stmt %s, start transform", S->getStmtClassName()); 71 | S->dump(); 72 | S->dumpPretty(resMgr.getCompilerInstance().getASTContext()); 73 | switch (S->getStmtClass()) { 74 | case Stmt::IfStmtClass: 75 | { 76 | ExtractIfCondVarDecl(dyn_cast(S)); 77 | break; 78 | } 79 | case Stmt::WhileStmtClass: 80 | { 81 | this->WhileToIf(S); 82 | break; 83 | } 84 | case Stmt::DoStmtClass: 85 | { 86 | this->DoToIf(S); 87 | break; 88 | } 89 | case Stmt::ForStmtClass: 90 | { 91 | this->ForToIf(S); 92 | break; 93 | } 94 | case Stmt::SwitchStmtClass: 95 | { 96 | this->SwitchToIf(S); 97 | break; 98 | } 99 | // add paren to child 100 | case Stmt::MemberExprClass: 101 | { 102 | if(MemberExpr *ME = dyn_cast(S)) { 103 | if(Expr *Base = ME->getBase()) { 104 | DPRINT("add paran to MemberExpr"); 105 | Expr *PE = BuildParenExpr(Base); 106 | ME->setBase(PE); 107 | parMap->addStmt(ME); 108 | } 109 | } 110 | break; 111 | } 112 | default: 113 | return true; 114 | } 115 | 116 | return true; 117 | } 118 | 119 | bool StmtPretransformer::ExtractIfCondVarDecl(IfStmt *S) { 120 | if(!S) { 121 | return false; 122 | } 123 | ASTContext &Ctx = this->resMgr.getCompilerInstance().getASTContext(); 124 | if(DeclStmt *stIfDcl = const_cast(S->getConditionVariableDeclStmt())) { 125 | Stmt *Parent = this->parMap->getParent(S); 126 | assert(Parent && "IfStmt should have a parent"); 127 | Expr* stDclRef = this->BuildVarDeclRefExpr(S->getConditionVariable()); 128 | Expr* newIfCond = this->BuildImpCastExprToType(stDclRef, Ctx.BoolTy, clang::CK_LValueToRValue); 129 | S->setConditionVariable(Ctx, NULL); 130 | S->setCond(newIfCond); 131 | 132 | StmtPtrSmallVector *compBody = new StmtPtrSmallVector(); 133 | compBody->push_back(stIfDcl); 134 | compBody->push_back(S); 135 | CompoundStmt *newStmt = StVecToCompound(compBody); 136 | delete compBody; 137 | 138 | this->replaceChild(Parent, S, newStmt); 139 | this->parMap->addStmt(Parent); 140 | } 141 | return true; 142 | } 143 | 144 | bool StmtPretransformer::WhileToIf(Stmt *S) { 145 | //FIXME memory leak 146 | DPRINT("while to if trans"); 147 | ASTContext &Ctx = resMgr.getCompilerInstance().getASTContext(); 148 | WhileStmt *whileSt = dyn_cast(S); 149 | 150 | //new LABELs 151 | LabelStmt *lblBegin = this->AddNewLabel(NULL); 152 | LabelStmt *lblContinue = this->AddNewLabel(NULL); 153 | LabelStmt *lblEnd = this->AddNewLabel(NULL); 154 | 155 | //convert contiue and break in subtree 156 | this->InnerJumpToGoto(S, lblContinue, lblEnd); 157 | 158 | //LABEL_CONTINUE: 159 | GotoStmt *gotoOfLblContinue = this->AddNewGoto(lblBegin); 160 | lblContinue->setSubStmt(gotoOfLblContinue); 161 | 162 | //new IfStmt 163 | VarDecl *varDcl = whileSt->getConditionVariable(); 164 | DeclStmt *oldDclSt = const_cast(whileSt->getConditionVariableDeclStmt()); 165 | Expr *condSt = whileSt->getCond(); 166 | Stmt *wBody = whileSt->getBody(); 167 | StmtPtrSmallVector *newIfBody = new StmtPtrSmallVector(); 168 | if(wBody) 169 | newIfBody->push_back(wBody); 170 | newIfBody->push_back(lblContinue); 171 | Stmt *stNewIfBody = this->StVecToCompound(newIfBody); 172 | IfStmt *ifSt = new (Ctx) 173 | IfStmt(Ctx, SourceLocation(), NULL, condSt, stNewIfBody); 174 | //this->updateChildrenInEdge(ifSt); 175 | //this->updateChildrenInEdge(stNewIfBody); 176 | 177 | //bind substmt to LABEL_BEGIN 178 | StmtPtrSmallVector *lblBeginBody = new StmtPtrSmallVector(); 179 | if(oldDclSt) { 180 | lblBeginBody->push_back(oldDclSt); 181 | } 182 | lblBeginBody->push_back(ifSt); 183 | lblBeginBody->push_back(lblEnd); 184 | Stmt *stLblBeginBody = this->StVecToCompound(lblBeginBody); 185 | lblBegin->setSubStmt(stLblBeginBody); 186 | //this->updateChildrenInEdge(stLblBeginBody); 187 | 188 | //change orignal WhileStmt to the lblBegin 189 | Stmt *Parent = this->parMap->getParent(S); 190 | replaceChild(Parent, S, lblBegin); 191 | this->parMap->addStmt(S); 192 | //S = lblBegin; 193 | 194 | //free memory 195 | delete newIfBody; 196 | delete lblBeginBody; 197 | 198 | return true; 199 | } 200 | 201 | bool StmtPretransformer::DoToIf(Stmt *S) { 202 | DPRINT("do to if trans"); 203 | ASTContext &Ctx = this->resMgr.getCompilerInstance().getASTContext(); 204 | DoStmt *DS = dyn_cast(S); 205 | 206 | //LABEL_BEGIN 207 | LabelStmt *lblBegin = this->AddNewLabel(NULL); 208 | LabelStmt *lblDo = this->AddNewLabel(NULL); 209 | LabelStmt *lblContinue = this->AddNewLabel(NULL); 210 | LabelStmt *lblEnd = this->AddNewLabel(NULL); 211 | 212 | //convert contiue and break in subtree 213 | this->InnerJumpToGoto(S, lblContinue, lblEnd); 214 | 215 | //LABEL_DO 216 | Stmt *oldDoBody = DS->getBody(); 217 | if(oldDoBody == NULL) 218 | oldDoBody = this->AddNewNullStmt(); 219 | lblDo->setSubStmt(oldDoBody); 220 | //this->updateChildrenInEdge(lblDo); 221 | 222 | //LABEL_CONTINUE 223 | GotoStmt *gotoOfLblContinue = this->AddNewGoto(lblBegin); 224 | Expr *whileCond = DS->getCond(); 225 | IfStmt *ifOfLblContinue = new (Ctx) 226 | IfStmt(Ctx, SourceLocation(), NULL, whileCond, gotoOfLblContinue); 227 | //this->updateChildrenInEdge(ifOfLblContinue); 228 | lblContinue->setSubStmt(ifOfLblContinue); 229 | 230 | //bind new body to LABEL_BEGIN 231 | StmtPtrSmallVector *lblBeginBody = new StmtPtrSmallVector(); //the outer most do label stmt 232 | lblBeginBody->push_back(lblDo); 233 | lblBeginBody->push_back(lblContinue); 234 | lblBeginBody->push_back(lblEnd); 235 | lblBegin->setSubStmt(this->StVecToCompound(lblBeginBody)); 236 | 237 | //change orignal DoStmt to the lblBegin 238 | replaceChild(this->parMap->getParent(S), S, lblBegin); 239 | this->parMap->addStmt(S); 240 | 241 | delete lblBeginBody; 242 | 243 | return true; 244 | } 245 | 246 | bool StmtPretransformer::ForToIf(Stmt *S) { 247 | DPRINT("for to if trans"); 248 | ASTContext &Ctx = this->resMgr.getCompilerInstance().getASTContext(); 249 | ForStmt *FS = dyn_cast(S); 250 | 251 | //outer most LABEL_FOR 252 | LabelStmt *lblFor = this->AddNewLabel(NULL); 253 | LabelStmt *lblBegin = this->AddNewLabel(NULL); 254 | LabelStmt *lblContinue = this->AddNewLabel(NULL); 255 | LabelStmt *lblEnd = this->AddNewLabel(NULL); 256 | 257 | //convert contiue and break in subtree 258 | this->InnerJumpToGoto(S, lblContinue, lblEnd); 259 | 260 | //LABEL_CONTINUE: 261 | StmtPtrSmallVector *lblContinueBody = new StmtPtrSmallVector(); 262 | Stmt *oldForInc = FS->getInc(); 263 | if(oldForInc) 264 | lblContinueBody->push_back(oldForInc); 265 | GotoStmt *jumpToLblBegin = this->AddNewGoto(lblBegin); 266 | lblContinueBody->push_back(jumpToLblBegin); 267 | //fill LABEL_CONTINUE: 268 | Stmt *stLblContinueBody = this->StVecToCompound(lblContinueBody); 269 | lblContinue->setSubStmt(stLblContinueBody); 270 | //this->updateChildrenInEdge(stLblContinueBody); 271 | 272 | //new If stmt 273 | StmtPtrSmallVector *newIfBody = new StmtPtrSmallVector(); // 274 | Stmt *oldForBody = FS->getBody(); 275 | if(oldForBody) 276 | newIfBody->push_back(oldForBody); 277 | newIfBody->push_back(lblContinue); 278 | Expr *oldForCond = FS->getCond(); 279 | //if cond is null, create a "true" expr 280 | if(oldForCond == NULL) { 281 | oldForCond = this->BuildCXXBoolLiteralExpr(true); 282 | } 283 | VarDecl *oldVarDcl = FS->getConditionVariable(); 284 | DeclStmt *oldDclSt = const_cast(FS->getConditionVariableDeclStmt()); 285 | Stmt *stNewIfBody = this->StVecToCompound(newIfBody); 286 | IfStmt *newIfSt = new (Ctx) 287 | IfStmt(Ctx, SourceLocation(), NULL, oldForCond, this->StmtToCompound(stNewIfBody)); 288 | //this->updateChildrenInEdge(newIfSt); 289 | //this->updateChildrenInEdge(stNewIfBody); 290 | 291 | //fill LABEL_BEGIN 292 | StmtPtrSmallVector lblBeginBody; 293 | if(oldDclSt) { 294 | lblBeginBody.push_back(oldDclSt); 295 | } 296 | lblBeginBody.push_back(newIfSt); 297 | lblBegin->setSubStmt(StVecToCompound(&lblBeginBody)); 298 | 299 | //fill LABEL_FOR 300 | StmtPtrSmallVector *lblForBody = new StmtPtrSmallVector(); // 301 | lblForBody->push_back(FS->getInit()); 302 | lblForBody->push_back(lblBegin); 303 | lblForBody->push_back(lblEnd); 304 | Stmt *stLblForBody = this->StVecToCompound(lblForBody); 305 | lblFor->setSubStmt(stLblForBody); 306 | //this->updateChildrenInEdge(stLblForBody); 307 | 308 | //modify old ForStmt 309 | replaceChild(this->parMap->getParent(S), S, lblFor); 310 | this->parMap->addStmt(S); 311 | 312 | delete lblContinueBody; 313 | delete newIfBody; 314 | delete lblForBody; 315 | 316 | return true; 317 | } 318 | 319 | //maybe has bug 320 | //need transform break->goto before case->label 321 | bool StmtPretransformer::SwitchToIf(Stmt *S) { 322 | DPRINT("switch to if trans"); 323 | ASTContext &Ctx = resMgr.getCompilerInstance().getASTContext(); 324 | SwitchStmt *SS = dyn_cast(S); 325 | 326 | //LABEL_SWITCH: 327 | DPRINT("LABEL_SWITCH"); 328 | LabelStmt *stLblSwitch = AddNewLabel(NULL); //to be filled 329 | 330 | //if no ConditionalVariable, create one 331 | // switch(a){...} to int t=(a); switch(t){..} 332 | if(!SS->getConditionVariable()) { 333 | DPRINT("create cond var"); 334 | Decl *D = declStack.back(); 335 | Expr *exprCond = SS->getCond(); 336 | DeclStmt *dclSt = CreateIntVar( 337 | NULL, 338 | BuildParenExpr(exprCond)); 339 | VarDecl *varDcl = dyn_cast(dclSt->getSingleDecl()); 340 | SS->setConditionVariable(Ctx, varDcl); 341 | SS->setCond(BuildImpCastExprToType(exprCond, varDcl->getType(), clang::CK_LValueToRValue)); 342 | } 343 | 344 | DPRINT("get switch sub ptr"); 345 | Expr *EC = SS->getCond(); 346 | DeclStmt *DS = const_cast(SS->getConditionVariableDeclStmt()); 347 | VarDecl *VD = SS->getConditionVariable(); 348 | 349 | DPRINT("create if "); 350 | //IfStmt go switch goto 351 | IfStmt *stSwIf = new (Ctx) IfStmt(Ctx, SourceLocation(), NULL, NULL, NULL); 352 | 353 | //switch body 354 | Stmt *stSwBody = SS->getBody(); 355 | 356 | //LABEL_BREAK: 357 | LabelStmt *stLblBreak = AddNewLabel(NULL); 358 | 359 | DPRINT("iterator case/default"); 360 | //process all cases 361 | //record default and add it last 362 | LabelStmt *stLblDefault = NULL; 363 | IfStmt *lastIf = NULL; 364 | for(SwitchCase *SC = SS->getSwitchCaseList(); 365 | SC; SC = SC->getNextSwitchCase()) { 366 | LabelStmt *stLblCase = AddNewLabel(NULL); 367 | 368 | //record the replacing stmt of CaseStmt 369 | StmtNodeMap::iterator it = this->stmtMap.find(SC); 370 | assert(it != this->stmtMap.end() && it->second && "stmt dfs info not found"); 371 | it->second->stNew = stLblCase; 372 | DPRINT("record case: (%x) %x %x %x", it->second, it->second->stOrig, it->second->pInEdge, it->second->stNew); 373 | 374 | if(isa(*SC)) { 375 | DPRINT("case stmt reached %x", SC); 376 | CaseStmt *stCase = dyn_cast(SC); 377 | 378 | //add if goto 379 | Expr *expL = stCase->getLHS(); 380 | Expr *expR = stCase->getRHS(); 381 | Expr *expIfCond = expR ? 382 | BuildRangeCondExpr(BuildVarDeclRefExpr(VD), expL, expR) 383 | : BuildEqualCondExpr(BuildVarDeclRefExpr(VD), expL); 384 | 385 | //goto LABEL_CASE 386 | GotoStmt *stGoto = AddNewGoto(stLblCase); 387 | DPRINT("set else if"); 388 | 389 | if(lastIf){ 390 | IfStmt *elseIf = new (Ctx) 391 | IfStmt(Ctx, SourceLocation(), NULL, expIfCond, stGoto); 392 | lastIf->setElse(elseIf); 393 | lastIf = elseIf; 394 | } else { 395 | stSwIf->setCond(expIfCond); 396 | stSwIf->setThen(stGoto); 397 | lastIf = stSwIf; 398 | } 399 | DPRINT("case stmt end"); 400 | } else if(isa(*SC)) { 401 | DPRINT("default stmt reached %x", SC); 402 | stLblDefault = stLblCase; 403 | DPRINT("default stmt end"); 404 | } else { 405 | assert(false && "SwitchCase type unknown"); 406 | } 407 | } 408 | //add the last else goto 409 | DPRINT("add last else goto"); 410 | GotoStmt *lastGoto = stLblDefault ? 411 | AddNewGoto(stLblDefault) 412 | : AddNewGoto(stLblBreak); 413 | if(lastIf) { 414 | lastIf->setElse(lastGoto); 415 | } else { 416 | stSwIf->setCond(BuildCXXBoolLiteralExpr(true)); // if(true) 417 | stSwIf->setThen(lastGoto); 418 | } 419 | 420 | DPRINT("transform break"); 421 | 422 | //preserve ContinueStmt 423 | for(int I = this->stmtStack.size()-1; 424 | I >= 0 && this->stmtStack[I]->stOrig != S; 425 | --I) { 426 | //Child is the orignal child, not nessessarily equal to *pChild 427 | StmtPretransInfo *node = this->stmtStack[I]; 428 | Stmt *Child = node->stOrig, **pChild = node->pInEdge, *Replace = node->stNew, *Parent = this->parMap->getParent(Child); 429 | 430 | //preserve ContinueStmt 431 | if(isa(Child)) { 432 | continue; 433 | } 434 | DPRINT("pop stmt %s (%x) %x %x %x", Child->getStmtClassName(), &node, Child, pChild, Replace); 435 | 436 | //transform break 437 | if(isa(Child)) { 438 | DPRINT("break reached"); 439 | GotoStmt *jumpToLblBreak = this->AddNewGoto(stLblBreak); 440 | //*pChild = jumpToLblBreak; //FIXME memory leak 441 | replaceChild(Parent, Child, jumpToLblBreak); 442 | DPRINT("break end"); 443 | } else if(isa(Child)) { 444 | DPRINT("SwitchCase reached %x", Child); 445 | //modify old case ptr 446 | SwitchCase *swCas = dyn_cast(Child); 447 | LabelStmt *lblSt = dyn_cast(Replace); 448 | lblSt->setSubStmt(swCas->getSubStmt()); 449 | //*pChild = Replace; //FIXME memory leak 450 | replaceChild(Parent, Child, Replace); 451 | DPRINT("switchCase ended"); 452 | } 453 | 454 | delete node; 455 | this->stmtStack.erase(this->stmtStack.begin() + I); 456 | this->stmtMap.erase(Child); 457 | } 458 | 459 | DPRINT("set new switch body"); 460 | 461 | StmtPtrSmallVector *lblSwitchBody = new StmtPtrSmallVector(); 462 | //T t=x; 463 | if(DS) 464 | lblSwitchBody->push_back(DS); 465 | lblSwitchBody->push_back(stSwIf); 466 | if(stSwBody) 467 | lblSwitchBody->push_back(stSwBody); 468 | lblSwitchBody->push_back(stLblBreak); 469 | Stmt *stLblSwitchBody = this->StVecToCompound(lblSwitchBody); 470 | 471 | //fill LABEL_SWITCH body 472 | stLblSwitch->setSubStmt(stLblSwitchBody); 473 | //this->updateChildrenInEdge(stLblSwitchBody); 474 | //modify parent ptr 475 | //S = stLblSwitch; 476 | replaceChild(this->parMap->getParent(S), S, stLblSwitch); 477 | this->parMap->addStmt(S); 478 | 479 | DPRINT("done"); 480 | 481 | delete lblSwitchBody; 482 | DPRINT("free memory"); 483 | 484 | return true; 485 | } 486 | 487 | //tranform break/continue in for, do, while stmt 488 | //remove other stmts in the dfs stack EXCEPT CaseStmt 489 | bool StmtPretransformer::InnerJumpToGoto(const Stmt *stRoot, LabelStmt *stLblContinue, LabelStmt *stLblBreak) { 490 | ASTContext &Ctx = resMgr.getCompilerInstance().getASTContext(); 491 | //convert contiue and break in subtree 492 | for(int I = this->stmtStack.size()-1; 493 | I >= 0 && this->stmtStack[I]->stOrig != stRoot; 494 | --I) { 495 | StmtPretransInfo *node = this->stmtStack[I]; 496 | Stmt *Child = node->stOrig, **pChild = node->pInEdge, *Replace = node->stNew, *Parent = this->parMap->getParent(Child); 497 | //preserve DefaultStmt/CastStmt 498 | if(isa(Child)) { 499 | continue; 500 | } 501 | DPRINT("pop stmt %s (%x) %x %x %x", Child->getStmtClassName(), &node, Child, pChild, Replace); 502 | 503 | if(isa(Child)) { 504 | if(stLblContinue) { 505 | GotoStmt *jumpToLblContinue = this->AddNewGoto(stLblContinue); 506 | replaceChild(Parent, Child, jumpToLblContinue); 507 | //*pChild = jumpToLblContinue; //FIXME: memory leak 508 | } 509 | } else if(isa(Child)) { 510 | if(stLblBreak) { 511 | GotoStmt *jumpToLblEnd = this->AddNewGoto(stLblBreak); 512 | replaceChild(Parent, Child, jumpToLblEnd); 513 | //*pChild = jumpToLblEnd; //FIXME: memory leak 514 | } 515 | } 516 | 517 | delete node; 518 | this->stmtStack.erase(this->stmtStack.begin() + I); 519 | this->stmtMap.erase(Child); 520 | } 521 | 522 | return true; 523 | } 524 | 525 | bool StmtPretransformer::updateChildrenInEdge(Stmt *S) { 526 | if(!S) { 527 | DPRINT("Stmt NULL"); 528 | return true; 529 | } 530 | //FIXME: inefficient, replace with a new data structure 531 | this->parMap->addStmt(S); 532 | /* 533 | for(Stmt::child_iterator I = S->child_begin(), IEnd = S->child_end(); 534 | I != IEnd; ++I) { 535 | StmtNodeMap::iterator it = stmtMap.find(S); 536 | if(it != stmtMap.end()) { 537 | it->second->pInEdge = &(*I); 538 | } 539 | } 540 | */ 541 | return true; 542 | } 543 | 544 | -------------------------------------------------------------------------------- /src/alg/FlattenCFG/StmtPretransformer.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_ALG_STMTPRETRANSFORMER_H 2 | #define OBFS_ALG_STMTPRETRANSFORMER_H 3 | 4 | #include "llvm/ADT/SmallVector.h" 5 | #include "llvm/ADT/DenseMap.h" 6 | #include "clang/AST/ParentMap.h" 7 | #include "alg/Algorithm.h" 8 | #include "alg/FlattenCFG/ASTTraverserPlus.h" 9 | #include 10 | using namespace clang; 11 | 12 | using llvm::SmallVector; 13 | using llvm::DenseMap; 14 | 15 | class StmtPretransInfo{ 16 | public: 17 | StmtPretransInfo(Stmt *O, Stmt **E, Stmt *N = 0) 18 | : stOrig(O), pInEdge(E), stNew(N) 19 | {} 20 | 21 | Stmt *stOrig; //original stmt in AST tree 22 | Stmt **pInEdge; //original stmt's parent's ptr that points in 23 | Stmt *stNew; //new stmt to replace old one 24 | }; 25 | 26 | class StmtPretransformer: public Algorithm, public ASTTraverserPlus{ 27 | public: 28 | typedef StmtPretransInfo *StmtPretransInfoPtrTy; 29 | typedef SmallVector StmtNodeSmallVector; 30 | typedef DenseMap StmtNodeMap; 31 | 32 | StmtPretransformer(ResourceManager &RM) 33 | : Algorithm(RM) 34 | {} 35 | 36 | bool HandleDecl(Decl *D); 37 | 38 | bool VisitStmt(Stmt *S); 39 | bool ExitStmt(Stmt *S); 40 | 41 | bool VisitDecl(Decl *D); 42 | bool ExitDecl(Decl *D); 43 | 44 | protected: 45 | //extract vardecl in ifcond to avoid dumpPretty bug: 46 | //if(T t=x){..} to T t=x; if(t){..} 47 | bool ExtractIfCondVarDecl(IfStmt *S); 48 | 49 | bool WhileToIf(Stmt *S); 50 | bool DoToIf(Stmt *S); 51 | bool ForToIf(Stmt *S); 52 | bool SwitchToIf(Stmt *S); 53 | 54 | bool InnerJumpToGoto(const Stmt *stRoot, LabelStmt *stLblContinue, LabelStmt *stLblBreak); 55 | 56 | //update stmtMap.pInEdge of children of S 57 | bool updateChildrenInEdge(Stmt *S); 58 | 59 | StmtNodeSmallVector stmtStack; //point to the Stmt* which points to a child 60 | DeclPtrSmallVector declStack; // point to the neariest enclosing Decl 61 | StmtNodeMap stmtMap; 62 | ParentMap *parMap; 63 | 64 | }; 65 | 66 | #endif 67 | -------------------------------------------------------------------------------- /src/alg/FlattenCFG/VarRenamer.cpp: -------------------------------------------------------------------------------- 1 | #include "VarRenamer.h" 2 | #include "clang/Rewrite/Core/Rewriter.h" 3 | using namespace std; 4 | using namespace clang; 5 | 6 | bool VarRenamer::HandleDecl(Decl *D) { 7 | //only rename vars in function, so far 8 | assert(isa(D) && "not a function decl"); 9 | DPRINT("START VarRenamer"); 10 | this->TraverseDecl(D); 11 | DPRINT("END VarRenamer"); 12 | return true; 13 | } 14 | 15 | bool VarRenamer::VisitDecl(Decl *&D) { 16 | if(!D){ 17 | return true; 18 | } 19 | 20 | DPRINT("decl: %s", D->getDeclKindName()); 21 | 22 | Rewriter &rw = resMgr.getRewriter(); 23 | if(VarDecl *VD = dyn_cast(D)) { 24 | DPRINT(" ---- name = %s | type = %s | desugared type = %s | const = %d | extern = %d | POD = %d", 25 | VD->getQualifiedNameAsString().c_str(), 26 | VD->getType().getAsString().c_str(), 27 | VD->getType().getDesugaredType(this->resMgr.getCompilerInstance().getASTContext()).getAsString().c_str(), 28 | VD->isConstexpr(), 29 | VD->hasExternalStorage(), 30 | VD->getType().isPODType(this->resMgr.getCompilerInstance().getASTContext())); 31 | if(VD->hasInit()) { 32 | VD->getInit()->dumpPretty(this->resMgr.getCompilerInstance().getASTContext()); 33 | } 34 | //TODO 35 | // don't rename global vars 36 | // don't rename extern vars 37 | QualType Ty = VD->getType(); 38 | if((VD->isLocalVarDecl() || isa(VD)) 39 | && !VD->hasExternalStorage()) { 40 | this->renameVarDecl(VD); 41 | //If is not in function body, then do rewrite here 42 | //FIXME rewrite should be done later in a specialized class 43 | if(isa(VD)) { 44 | rw.ReplaceText(SourceRange(VD->getLocation()), VD->getName()); 45 | } 46 | } 47 | } else if(isa(D)) { //class/union/struct/enum 48 | TagDecl *TD = dyn_cast(D); 49 | //rename all, no matter anoyomous or not 50 | //if( !TD->getIdentifier() 51 | // && !TD->getTypedefNameForAnonDecl()) { 52 | this->renameTagDecl(TD); 53 | //} 54 | } else if(isa(D)) { //enum constant 55 | EnumConstantDecl *ECD = dyn_cast(D); 56 | this->renameVarDecl(ECD); 57 | } 58 | //TODO typedef rename 59 | return true; 60 | } 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /src/alg/FlattenCFG/VarRenamer.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_ALG_VarRenamer_H 2 | #define OBFS_ALG_VarRenamer_H 3 | 4 | #include "alg/Algorithm.h" 5 | #include "alg/FlattenCFG/ASTTraverserPlus.h" 6 | using namespace clang; 7 | 8 | class VarRenamer; 9 | 10 | // rename these with unique identifiers: 11 | // local vars 12 | // enum members 13 | 14 | class VarRenamer: public Algorithm, public ASTTraverserPlus { 15 | public: 16 | VarRenamer(ResourceManager &RM) 17 | : Algorithm(RM) 18 | {} 19 | 20 | bool HandleDecl(Decl *D); 21 | 22 | //bool VisitStmt(Stmt *&S); 23 | bool VisitDecl(Decl *&D); 24 | 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/alg/InitParseConsumer.cpp: -------------------------------------------------------------------------------- 1 | #include "InitParseConsumer.h" 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/alg/InitParseConsumer.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_ALG_INITPARSECONSUMER_H 2 | #define OBFS_ALG_INITPARSECONSUMER_H 3 | 4 | #include "stdafx.h" 5 | #include "Typedef.h" 6 | #include "clang/AST/Decl.h" 7 | #include "clang/AST/DeclGroup.h" 8 | #include "clang/AST/ASTConsumer.h" 9 | #include "clang/Frontend/CompilerInstance.h" 10 | 11 | class InitParseConsumer : public clang::ASTConsumer { 12 | protected: 13 | DeclGroupRefVec &decls; 14 | clang::CompilerInstance *compInst; 15 | 16 | public: 17 | InitParseConsumer(DeclGroupRefVec &DV, clang::CompilerInstance *CI) 18 | : decls(DV), 19 | compInst(CI) 20 | {} 21 | ~InitParseConsumer(){} 22 | 23 | virtual bool HandleTopLevelDecl(clang::DeclGroupRef DR) { 24 | clang::Decl *firstD = *DR.begin(); 25 | if(compInst->getSourceManager().isInSystemHeader(firstD->getLocation())) { 26 | return true; 27 | } 28 | 29 | decls.push_back(DR); 30 | DPRINT("+decl, size = %d", decls.size()); 31 | return true; 32 | } 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/alg/SimplePrinter.cpp: -------------------------------------------------------------------------------- 1 | #include "SimplePrinter.h" 2 | #include "SimplePrinterConsumer.h" 3 | using namespace clang; 4 | 5 | bool 6 | SimplePrinter::execute() { 7 | DPRINT("alg started."); 8 | //DeclGroupRefVec &decls = resMgr.getDeclGroupRefVec(); 9 | TranslationUnitDecl *tud = resMgr.getCompilerInstance().getASTContext().getTranslationUnitDecl(); 10 | SimplePrinterConsumer consumer(llvm::errs(), &resMgr.getCompilerInstance()); 11 | /* 12 | for(int i = 0; i < decls.size(); i++) { 13 | consumer.HandleTopLevelDecl(decls[i]); 14 | } 15 | */ 16 | for(TranslationUnitDecl::decl_iterator I = tud->decls_begin(), E = tud->decls_end(); 17 | I != E; ++I){ 18 | //consumer.HandleTopLevelDecl(*I); 19 | SourceLocation Loc = (*I)->getLocation(); 20 | if(Loc.isInvalid() || 21 | compInst.getSourceManager().isInSystemHeader(Loc)) { 22 | continue; 23 | } 24 | consumer.HandleTopLevelDecl(DeclGroupRef(*I)); 25 | } 26 | DPRINT("alg finished."); 27 | return true; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /src/alg/SimplePrinter.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_ALG_SIMPLEPRINTER_H 2 | #define OBFS_ALG_SIMPLEPRINTER_H 3 | 4 | #include "Algorithm.h" 5 | 6 | class SimplePrinter: public Algorithm { 7 | public: 8 | SimplePrinter(ResourceManager &RM) 9 | : Algorithm(RM) 10 | {} 11 | 12 | virtual bool execute(); 13 | 14 | protected: 15 | 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/alg/SimplePrinterConsumer.cpp: -------------------------------------------------------------------------------- 1 | #include "SimplePrinterConsumer.h" 2 | #include "clang/AST/ASTContext.h" 3 | #include "clang/AST/RecursiveASTVisitor.h" 4 | #include "clang/AST/ParentMap.h" 5 | #include "clang/Analysis/CFG.h" 6 | using namespace clang; 7 | 8 | class StmtPrinter : public RecursiveASTVisitor { 9 | public: 10 | StmtPrinter(CompilerInstance *CI, Stmt *S) 11 | : compInst(CI), 12 | parMap(new ParentMap(S)) 13 | {} 14 | 15 | bool VisitStmt(Stmt *s) { 16 | ASTContext &Ctx = compInst->getASTContext(); 17 | DPRINT("Stmt %s ( %u -> p %u )", s->getStmtClassName(), (unsigned int)s, (unsigned int)(parMap.get() ? parMap.get()->getParent(s) : 0)); 18 | s->dump(); 19 | s->dumpPretty(Ctx); 20 | NullStmt(SourceLocation()).dumpPretty(Ctx); 21 | return true; 22 | } 23 | 24 | protected: 25 | CompilerInstance *compInst; 26 | OwningPtr parMap; 27 | }; 28 | 29 | bool 30 | SimplePrinterConsumer::HandleTopLevelDecl(DeclGroupRef D) { 31 | if(D.begin() == D.end()) { 32 | return true; 33 | } 34 | Decl *firstD = *(D.begin()); 35 | if(compInst->getSourceManager().isInSystemHeader(firstD->getLocation())) { 36 | return true; 37 | } 38 | 39 | PrintingPolicy policy = compInst->getASTContext().getPrintingPolicy(); 40 | NullStmt *nullSt = new (compInst->getASTContext()) NullStmt(SourceLocation()); 41 | 42 | for(DeclGroupRef::iterator 43 | I = D.begin(), E = D.end(); 44 | I != E; ++I) { 45 | Decl *dd = *I; 46 | 47 | DPRINT("PrintingPolicy: %d %d %d %d %d", policy.SuppressSpecifiers, policy.SuppressScope, policy.SuppressTag, policy.SuppressUnwrittenScope, policy.SuppressSpecifiers); 48 | 49 | dd->print(out, policy); 50 | nullSt->printPretty(out, NULL, policy); 51 | if(dd->hasBody()) { 52 | Stmt *ss = dd->getBody(); 53 | // Print Stmts 54 | //dd->dump(); 55 | //StmtPrinter(compInst, dd->getBody()).TraverseDecl(dd); 56 | 57 | // CFG 58 | 59 | OwningPtr cfg; 60 | cfg.reset(CFG::buildCFG((const Decl*)dd, (Stmt*)(dd->getBody()), &compInst->getASTContext(), CFG::BuildOptions())); 61 | assert(cfg.get() != NULL && "build CFG failed."); 62 | cfg->dump(compInst->getLangOpts(), true); 63 | cfg->viewCFG(compInst->getLangOpts()); 64 | } 65 | } 66 | return true; 67 | }; 68 | 69 | -------------------------------------------------------------------------------- /src/alg/SimplePrinterConsumer.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_ALG_SIMPLEPRINTERCONSUMER_H 2 | #define OBFS_ALG_SIMPLEPRINTERCONSUMER_H 3 | 4 | #include "stdafx.h" 5 | #include "clang/AST/ASTConsumer.h" 6 | #include "clang/Frontend/CompilerInstance.h" 7 | #include "llvm/Support/raw_ostream.h" 8 | 9 | class SimplePrinterConsumer : public clang::ASTConsumer { 10 | protected: 11 | llvm::raw_ostream &out; 12 | clang::CompilerInstance *compInst; 13 | 14 | public: 15 | SimplePrinterConsumer(llvm::raw_ostream &O, clang::CompilerInstance *CI) 16 | : out(O), 17 | compInst(CI) 18 | {} 19 | ~SimplePrinterConsumer(){} 20 | 21 | virtual bool HandleTopLevelDecl(clang::DeclGroupRef D); 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/obfs.cpp: -------------------------------------------------------------------------------- 1 | #include "obfs.h" 2 | 3 | #include "stdafx.h" 4 | #include "Obfuscator.h" 5 | #include 6 | using std::cout; 7 | 8 | int main(int argc, char **argv) { 9 | //assert(argc == 2 && "No input file is specified."); 10 | Obfuscator obfs; 11 | obfs.init(); 12 | cout << "done1" << endl; 13 | obfs.doit(argc, argv); 14 | cout << "done2" << endl; 15 | 16 | return 0; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/obfs.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_OBFS_H 2 | #define OBFS_OBFS_H 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /src/res/OptionTable.cpp: -------------------------------------------------------------------------------- 1 | #include "res/OptionTable.h" 2 | #include "stdafx.h" 3 | #include 4 | #include 5 | using namespace std; 6 | 7 | bool OptionTable::ParseArgs(int argc, char** argv) { 8 | DPRINT("argc = %d", argc); 9 | for(unsigned i = options::Invalid; i != options::EndOption; ++i) { 10 | impl[i].clear(); 11 | } 12 | // FIXME: shortname 13 | string shortOpt; 14 | int choose; 15 | int longind; 16 | while((choose = getopt_long(argc, argv, shortOpt.c_str(), options::InfoTable, &longind)) != -1) { 17 | switch(choose) { 18 | case options::OPT_Directory: 19 | assert(impl[choose].size() == 0 && "Can't output to multiple directories."); 20 | impl[choose].push_back(optarg); 21 | DPRINT("Output Directory: %s", optarg); 22 | break; 23 | // FIXME: implement 24 | case options::OPT_ScopeMode: 25 | case options::OPT_ScopeIncludeFlag: 26 | case options::OPT_ScopeExcludeFlag: 27 | case options::OPT_CustomObfsArg: 28 | case options::OPT_CustomClangArg: 29 | default: 30 | DPRINT("Option not implemented yet: [%s] [%s]", options::InfoTable[longind].name, optarg); 31 | break; 32 | } 33 | } 34 | 35 | // get input file name 36 | if(optind < argc) { 37 | while(optind < argc) { 38 | DPRINT("non-option argvs caught: [%s]", argv[optind]); 39 | impl[options::Argument].push_back(argv[optind++]); 40 | } 41 | } 42 | // TODO: support multiple src files 43 | assert(impl[options::Argument].size() == 1 && 44 | "Should set exactly 1 src file."); 45 | 46 | return true; 47 | } 48 | 49 | OptionTable::OptValueListTy& OptionTable::getOption(options::OPTID ID) { 50 | assert(ID >= options::Invalid && ID < options::EndOption 51 | && "Option ID out of bound."); 52 | return impl[ID]; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/res/OptionTable.h: -------------------------------------------------------------------------------- 1 | #ifndef OBFS_RES_OPTIONTABLE_H 2 | #define OBFS_RES_OPTIONTABLE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using std::vector; 9 | using std::string; 10 | 11 | // FIXME: implement class Option 12 | 13 | //#define OPTION(NAME, HAS_ARG, FLAG, ID, SHORT, HELPTEXT) 14 | 15 | //Option ID list 16 | namespace options { 17 | enum OPTID { 18 | Invalid = 0, 19 | #define OPTION(NAME, HAS_ARG, FLAG, ID, SHORT, HELPTEXT) \ 20 | OPT_##ID, 21 | #include "res/Options.inc" 22 | Argument, 23 | EndOption 24 | #undef OPTION 25 | }; 26 | 27 | //Option List 28 | static option InfoTable[] = { 29 | #define OPTION(NAME, HAS_ARG, FLAG, ID, SHORT, HELPTEXT) \ 30 | {NAME, HAS_ARG, FLAG, OPT_##ID}, 31 | #include "res/Options.inc" 32 | #undef OPTION 33 | {0, 0, 0, 0} 34 | }; 35 | 36 | } 37 | 38 | // This class parses and stores options passed into main(). 39 | class OptionTable { 40 | public: 41 | typedef vector OptValueListTy; 42 | typedef vector OptPoolTy; 43 | 44 | protected: 45 | OptPoolTy impl; 46 | 47 | public: 48 | OptionTable(int argc, char **argv) 49 | : impl(OptPoolTy(options::EndOption)) 50 | { 51 | this->ParseArgs(argc, argv); 52 | } 53 | 54 | // Parse and store args 55 | bool ParseArgs(int argc, char **argv); 56 | 57 | // Get all values of option ID 58 | OptValueListTy& getOption(options::OPTID ID); 59 | }; 60 | 61 | #endif 62 | 63 | -------------------------------------------------------------------------------- /src/res/Options.inc: -------------------------------------------------------------------------------- 1 | #ifndef OPTION 2 | #error "Define OPTION prior to including this file!" 3 | #endif 4 | 5 | #include 6 | 7 | //Options 8 | OPTION("directory", required_argument, 0, Directory, "d", 0) 9 | OPTION("scope-mode", required_argument, 0, ScopeMode, 0, 0) 10 | OPTION("scope-include-flag", required_argument, 0, ScopeIncludeFlag, 0, 0) 11 | OPTION("scope-exclude-flag", required_argument, 0, ScopeExcludeFlag, 0, 0) 12 | OPTION("obfs", required_argument, 0, CustomObfsArg, 0, 0) 13 | OPTION("Xclang", required_argument, 0, CustomClangArg, 0, 0) 14 | 15 | -------------------------------------------------------------------------------- /src/stdafx.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDAFX_H_ 2 | #define _STDAFX_H_ 3 | #include 4 | #include 5 | 6 | /* 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include // for basename(), dirname(), etc. 12 | 13 | #include "clang/AST/ASTConsumer.h" 14 | #include "clang/AST/RecursiveASTVisitor.h" 15 | #include "clang/AST/ParentMap.h" 16 | #include "clang/Basic/LangOptions.h" 17 | #include "clang/Basic/Version.h" 18 | #include "clang/Basic/Diagnostic.h" 19 | #include "clang/Basic/FileManager.h" 20 | #include "clang/Basic/SourceManager.h" 21 | #include "clang/Basic/TargetOptions.h" 22 | #include "clang/Basic/TargetInfo.h" 23 | #include "clang/Frontend/FrontendOptions.h" 24 | #include "clang/Frontend/CompilerInstance.h" 25 | #include "clang/Lex/Preprocessor.h" 26 | #include "clang/Lex/HeaderSearch.h" 27 | #include "clang/Sema/Sema.h" 28 | #include "clang/Parse/ParseAST.h" 29 | #include "clang/Parse/Parser.h" 30 | #include "clang/Rewrite/Rewriter.h" 31 | #include "clang/Rewrite/Rewriters.h" 32 | #include "clang/Analysis/CFG.h" 33 | #include "llvm/Support/Host.h" 34 | #include "llvm/Support/raw_ostream.h" 35 | <<<<<<< Updated upstream 36 | ======= 37 | 38 | >>>>>>> Stashed changes 39 | */ 40 | 41 | #define DEBUG 42 | #ifdef DEBUG 43 | #define DPRINT(fmt, ...) \ 44 | fprintf(stderr, "[DEBUG][%s - line %d] ", __FILE__, __LINE__); \ 45 | fprintf(stderr, fmt, ## __VA_ARGS__); \ 46 | fprintf(stderr, "\n"); 47 | #endif 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /test/_.__array.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | void declref() { 7 | int ____localvar____0[3][3][2]; 8 | int ____localvar____1 = 1; 9 | while (____localvar____1 != 0) 10 | switch (int ____localvar____1 = 1) { 11 | case 1: 12 | { 13 | ____localvar____0[0][0][0] = 1; 14 | ____localvar____0[0][0][1] = 2; 15 | ____localvar____0[0][1][0] = 3; 16 | ____localvar____0[2][0][0] = 3; 17 | ____localvar____0[2][1][0] = 9; 18 | ____localvar____0[2][1][1] = 8; 19 | ____localvar____0[0][0][1] = 0; 20 | break; 21 | } 22 | } 23 | } 24 | 25 | 26 | void classref() { 27 | string ____localvar____2[2][2]; 28 | vector ____localvar____3; 29 | int ____localvar____4 = 1; 30 | while (____localvar____4 != 0) 31 | switch (int ____localvar____4 = 1) { 32 | case 1: 33 | { 34 | ____localvar____2[1][0] = std::basic_string("xx"); 35 | ____localvar____2[1][1] = std::basic_string(string("yyy")); 36 | ____localvar____3 = std::vector, std::allocator > >(); 37 | ____localvar____3[2][3] = 'x'; 38 | break; 39 | } 40 | } 41 | } 42 | 43 | 44 | int main() { 45 | int ____localvar____5 = 1; 46 | while (____localvar____5 != 0) 47 | switch (int ____localvar____5 = 1) { 48 | case 1: 49 | { 50 | return 0; 51 | break; 52 | } 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /test/_.__cond.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int ifif() { 4 | int ____localvar____0; 5 | int ____localvar____1; 6 | int ____localvar____2; 7 | int ____localvar____3; 8 | int ____localvar____4; 9 | int ____localvar____5 = 9; 10 | while (____localvar____5 != 0) 11 | switch (int ____localvar____5 = 9) { 12 | case 1: 13 | { 14 | return 2; 15 | break; 16 | } 17 | case 2: 18 | { 19 | ____localvar____4 = ____localvar____0 , ____localvar____1 , ____localvar____2; 20 | return 0; 21 | break; 22 | } 23 | case 3: 24 | { 25 | if (____localvar____2 , ____localvar____3 , ____localvar____0 || (____localvar____1 || ____localvar____4) || (____localvar____2 && ____localvar____3) || (~____localvar____1)) { 26 | ____localvar____5 = 2; 27 | } else { 28 | ____localvar____5 = 1; 29 | } 30 | ____localvar____5 = 2; 31 | break; 32 | } 33 | case 9: 34 | { 35 | ____localvar____5 = 3; 36 | break; 37 | } 38 | } 39 | } 40 | 41 | 42 | int main() { 43 | int ____localvar____6; 44 | int ____localvar____7; 45 | int ____localvar____8 = 4; 46 | while (____localvar____8 != 0) 47 | switch (int ____localvar____8 = 4) { // should be ____localvar____8 48 | case 1: 49 | { 50 | ____localvar____7 = (____localvar____6) ? 1 : 0; 51 | return 0; 52 | break; 53 | } 54 | case 4: 55 | { 56 | ____localvar____6 = 0; 57 | ____localvar____8 = 1; 58 | break; 59 | } 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /test/_.__const.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | //const array 6 | void const_initlist() { 7 | const char *____localvar____0[2]; 8 | const char *____localvar____1; 9 | char *____localvar____2; 10 | int ____localvar____3 = 1; 11 | while (____localvar____3 != 0) 12 | switch (int ____localvar____3 = 1) { 13 | case 1: 14 | { 15 | ____localvar____0[0] = "a"; 16 | ____localvar____0[1] = "b"; 17 | ____localvar____1 = "xx"; 18 | ____localvar____2 = "yy"; 19 | break; 20 | } 21 | } 22 | } 23 | 24 | 25 | 26 | //const reference 27 | string gs; 28 | const string &func() { 29 | int ____localvar____4 = 1; 30 | while (____localvar____4 != 0) 31 | switch (int ____localvar____4 = 1) { 32 | case 1: 33 | { 34 | return gs; 35 | break; 36 | } 37 | } 38 | } 39 | 40 | 41 | int main() 42 | { 43 | int *____localvar____5; 44 | string ____localvar____6; 45 | char *____localvar____7; 46 | std::basic_string ____localvar____8; 47 | string *____localvar____9; 48 | string *____localvar____16; 49 | string *____localvar____11; 50 | char *____localvar____12; 51 | const char *____localvar____13; 52 | char ____localvar____14[]; 53 | char *____localvar____15; 54 | int ____localvar____17 = 1; 55 | while (____localvar____17 != 0) 56 | switch (int ____localvar____17 = 1) { 57 | case 1: 58 | { 59 | const_initlist(); 60 | ____localvar____5 = (int *)new const int(1024); 61 | printf("%d ", *____localvar____5); 62 | *____localvar____5 = 20; 63 | printf("%d\n", *____localvar____5); 64 | ____localvar____6 = std::basic_string(); 65 | ____localvar____7 = (char *)(____localvar____6).c_str(); 66 | ____localvar____8 = std::basic_string("xxxxxx"); 67 | ____localvar____7 = (char *)(____localvar____8).c_str(); 68 | ____localvar____9 = (string *)&func(); 69 | ____localvar____16 = &(const_cast(func())); 70 | ____localvar____11 = &(const_cast(func())); 71 | ____localvar____12 = const_cast(&("haha")[0]); 72 | ____localvar____13 = &("haha")[0]; 73 | return 0; 74 | break; 75 | } 76 | } 77 | } 78 | 79 | -------------------------------------------------------------------------------- /test/_.__for.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int ____localvar____0, char **____localvar____1) 4 | { 5 | int ____localvar____2; 6 | int ____localvar____3 = 14; 7 | while (____localvar____3 != 0) 8 | switch (int ____localvar____3 = 14) { 9 | case 1: 10 | { 11 | ____label____3: 12 | ; 13 | break; 14 | } 15 | case 2: 16 | { 17 | ____label____2: 18 | ; 19 | ____localvar____3 = 12; 20 | break; 21 | } 22 | case 4: 23 | { 24 | ____localvar____3 = 2; 25 | break; 26 | } 27 | case 5: 28 | { 29 | ____localvar____3 = 4; 30 | break; 31 | } 32 | case 6: 33 | { 34 | ____localvar____3 = 1; 35 | break; 36 | } 37 | case 7: 38 | { 39 | LABEL2: 40 | ; 41 | ____localvar____3 = 6; 42 | break; 43 | } 44 | case 8: 45 | { 46 | LABEL1: 47 | ; 48 | ____localvar____3 = 7; 49 | break; 50 | } 51 | case 9: 52 | { 53 | LABEL0: 54 | ; 55 | ____localvar____3 = 8; 56 | break; 57 | } 58 | case 10: 59 | { 60 | break; 61 | } 62 | case 11: 63 | { 64 | break; 65 | } 66 | case 12: 67 | { 68 | ____label____1: 69 | ; 70 | if (____localvar____2 < 13) { 71 | ____localvar____3 = 11; 72 | } else { 73 | ____localvar____3 = 10; 74 | } 75 | ____localvar____3 = 11; 76 | break; 77 | } 78 | case 13: 79 | { 80 | ____label____0: 81 | ; 82 | ____localvar____2 = 0; 83 | ____localvar____3 = 12; 84 | break; 85 | } 86 | case 14: 87 | { 88 | ____localvar____3 = 13; 89 | break; 90 | } 91 | } 92 | } 93 | 94 | 95 | -------------------------------------------------------------------------------- /test/_.__function.cpp: -------------------------------------------------------------------------------- 1 | int parm_fun(int ____localvar____0, int ____localvar____1 = 0) { 2 | int ____localvar____2 = 1; 3 | while (____localvar____2 != 0) 4 | switch (int ____localvar____2 = 1) { 5 | case 1: 6 | { 7 | return ____localvar____0 + ____localvar____1; 8 | break; 9 | } 10 | } 11 | } 12 | 13 | 14 | int pow() { 15 | int ____localvar____3; 16 | int ____localvar____4; 17 | int ____localvar____5 = 1; 18 | while (____localvar____5 != 0) 19 | switch (int ____localvar____5 = 1) { 20 | case 1: 21 | { 22 | ____localvar____3 = 0; 23 | ____localvar____3 += pow(); 24 | ____localvar____4 = 1; 25 | ____localvar____3 += ____localvar____4 , ____localvar____4 += ____localvar____3 , ____localvar____4 += ____localvar____4; 26 | return ____localvar____3; 27 | break; 28 | } 29 | } 30 | } 31 | 32 | 33 | int main() { 34 | int ____localvar____6 = 1; 35 | while (____localvar____6 != 0) 36 | switch (int ____localvar____6 = 1) { 37 | case 1: 38 | { 39 | return 0; 40 | break; 41 | } 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /test/_.__gcd_ob.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double fast_pow(double ____localvar____5, int ____localvar____6) { 4 | double ____localvar____7; 5 | int ____localvar____8; 6 | int ____localvar____9; 7 | int ____localvar____10 = 27; 8 | while (____localvar____10 != 0) 9 | switch (int ____localvar____10 = 27) { 10 | case 1: 11 | { 12 | ____label____9: 13 | ; 14 | break; 15 | } 16 | case 2: 17 | { 18 | ____label____8: 19 | ; 20 | ____localvar____10 = 26; 21 | break; 22 | } 23 | case 3: 24 | { 25 | ____label____1: 26 | ; 27 | ____localvar____10 = 2; 28 | break; 29 | } 30 | case 4: 31 | { 32 | ____localvar____10 = 3; 33 | break; 34 | } 35 | case 5: 36 | { 37 | ____localvar____8 = 3; 38 | ____localvar____10 = 4; 39 | break; 40 | } 41 | case 6: 42 | { 43 | ____localvar____8 = 4; 44 | ____localvar____10 = 4; 45 | break; 46 | } 47 | case 7: 48 | { 49 | ____label____2: 50 | ; 51 | if (____localvar____6 == 0) { 52 | ____localvar____10 = 6; 53 | } else { 54 | ____localvar____10 = 5; 55 | } 56 | ____localvar____10 = 6; 57 | break; 58 | } 59 | case 8: 60 | { 61 | ____label____3: 62 | ; 63 | return 1; 64 | break; 65 | } 66 | case 9: 67 | { 68 | ____localvar____10 = 3; 69 | break; 70 | } 71 | case 10: 72 | { 73 | ____localvar____8 = 1; 74 | ____localvar____10 = 9; 75 | break; 76 | } 77 | case 11: 78 | { 79 | ____localvar____8 = 2; 80 | ____localvar____10 = 9; 81 | break; 82 | } 83 | case 12: 84 | { 85 | ____label____4: 86 | ; 87 | ____localvar____7 = fast_pow(____localvar____5, ____localvar____6 / 2); 88 | if (____localvar____6 % 2 == 0) { 89 | ____localvar____10 = 11; 90 | } else { 91 | ____localvar____10 = 10; 92 | } 93 | ____localvar____10 = 11; 94 | break; 95 | } 96 | case 13: 97 | { 98 | ____label____5: 99 | ; 100 | return ____localvar____7 * ____localvar____7; 101 | break; 102 | } 103 | case 14: 104 | { 105 | ____label____6: 106 | ; 107 | return ____localvar____7 * ____localvar____7 * ____localvar____5; 108 | break; 109 | } 110 | case 15: 111 | { 112 | ____localvar____10 = 3; 113 | break; 114 | } 115 | case 16: 116 | { 117 | ____localvar____10 = 14; 118 | break; 119 | } 120 | case 17: 121 | { 122 | if (____localvar____9 == 1) { 123 | ____localvar____10 = 16; 124 | } else { 125 | ____localvar____10 = 15; 126 | } 127 | ____localvar____10 = 16; 128 | break; 129 | } 130 | case 18: 131 | { 132 | ____localvar____10 = 13; 133 | break; 134 | } 135 | case 19: 136 | { 137 | if (____localvar____9 == 2) { 138 | ____localvar____10 = 18; 139 | } else { 140 | ____localvar____10 = 17; 141 | } 142 | ____localvar____10 = 18; 143 | break; 144 | } 145 | case 20: 146 | { 147 | ____localvar____10 = 12; 148 | break; 149 | } 150 | case 21: 151 | { 152 | if (____localvar____9 == 3) { 153 | ____localvar____10 = 20; 154 | } else { 155 | ____localvar____10 = 19; 156 | } 157 | ____localvar____10 = 20; 158 | break; 159 | } 160 | case 22: 161 | { 162 | ____localvar____10 = 8; 163 | break; 164 | } 165 | case 23: 166 | { 167 | if (____localvar____9 == 4) { 168 | ____localvar____10 = 22; 169 | } else { 170 | ____localvar____10 = 21; 171 | } 172 | ____localvar____10 = 22; 173 | break; 174 | } 175 | case 24: 176 | { 177 | ____localvar____10 = 7; 178 | break; 179 | } 180 | case 25: 181 | { 182 | ____label____0: 183 | ; 184 | ____localvar____9 = (____localvar____8); 185 | if (____localvar____9 == 5) { 186 | ____localvar____10 = 24; 187 | } else { 188 | ____localvar____10 = 23; 189 | } 190 | ____localvar____10 = 24; 191 | break; 192 | } 193 | case 26: 194 | { 195 | ____label____7: 196 | ; 197 | if (____localvar____8 != 0) { 198 | ____localvar____10 = 25; 199 | } else { 200 | ____localvar____10 = 1; 201 | } 202 | ____localvar____10 = 25; 203 | break; 204 | } 205 | case 27: 206 | { 207 | ____localvar____8 = 5; 208 | ____localvar____10 = 26; 209 | break; 210 | } 211 | } 212 | } 213 | 214 | 215 | 216 | int main() { 217 | int ____localvar____11; 218 | int ____localvar____12; 219 | int ____localvar____13 = 9; 220 | while (____localvar____13 != 0) 221 | switch (int ____localvar____13 = 9) { 222 | case 1: 223 | { 224 | ____label____15: 225 | ; 226 | break; 227 | } 228 | case 2: 229 | { 230 | ____label____14: 231 | ; 232 | ____localvar____13 = 8; 233 | break; 234 | } 235 | case 3: 236 | { 237 | ____label____11: 238 | ; 239 | ____localvar____13 = 2; 240 | break; 241 | } 242 | case 4: 243 | { 244 | ____label____12: 245 | ; 246 | std::cout << fast_pow(2, 17) << std::endl; 247 | return 0; 248 | break; 249 | } 250 | case 5: 251 | { 252 | ____localvar____13 = 3; 253 | break; 254 | } 255 | case 6: 256 | { 257 | ____localvar____13 = 4; 258 | break; 259 | } 260 | case 7: 261 | { 262 | ____label____10: 263 | ; 264 | ____localvar____12 = 1; 265 | if (____localvar____12 == 1) { 266 | ____localvar____13 = 6; 267 | } else { 268 | ____localvar____13 = 5; 269 | } 270 | ____localvar____13 = 6; 271 | break; 272 | } 273 | case 8: 274 | { 275 | ____label____13: 276 | ; 277 | if (____localvar____11 != 0) { 278 | ____localvar____13 = 7; 279 | } else { 280 | ____localvar____13 = 1; 281 | } 282 | ____localvar____13 = 7; 283 | break; 284 | } 285 | case 9: 286 | { 287 | ____localvar____11 = 1; 288 | ____localvar____13 = 8; 289 | break; 290 | } 291 | } 292 | } 293 | 294 | 295 | 296 | -------------------------------------------------------------------------------- /test/_.__map.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int ____localvar____0 = 1; 5 | while (____localvar____0 != 0) 6 | switch (int ____localvar____0 = 1) { 7 | case 1: 8 | { 9 | return 0; 10 | break; 11 | } 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /test/_.__ref.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | /* 5 | void func(int *&x) { 6 | printf("%d\n", *x); 7 | 8 | } 9 | 10 | */ 11 | void ref_in_expr(int *____localvar____0) { 12 | int **____localvar____5; 13 | int **____localvar____2; 14 | int ____localvar____3; 15 | class ____localtag____0 { 16 | void func() { 17 | int ____localvar____4; 18 | ____localvar____4 = 1; 19 | } 20 | 21 | 22 | }; 23 | int ____localvar____6 = 6; 24 | while (____localvar____6 != 0) 25 | switch (int ____localvar____6 = 6) { 26 | case 1: 27 | { 28 | ____label____3: 29 | ; 30 | break; 31 | } 32 | case 2: 33 | { 34 | ____label____2: 35 | ; 36 | ____localvar____6 = 4; 37 | break; 38 | } 39 | case 3: 40 | { 41 | ____localvar____3 = 0; 42 | ____localvar____6 = 2; 43 | break; 44 | } 45 | case 4: 46 | { 47 | ____label____1: 48 | ; 49 | if (true) { 50 | ____localvar____6 = 3; 51 | } else { 52 | ; 53 | } 54 | ____localvar____6 = 3; 55 | break; 56 | } 57 | case 5: 58 | { 59 | ____label____0: 60 | ; 61 | ____localvar____6 = 4; 62 | break; 63 | } 64 | case 6: 65 | { 66 | ____localvar____5 = &(____localvar____0); 67 | *(*____localvar____5) = (*____localvar____0 + *((*____localvar____5) + 1)) - (*____localvar____5)[-1]; 68 | ____localvar____2 = &(*____localvar____5); 69 | ____localvar____6 = 5; 70 | break; 71 | } 72 | } 73 | } 74 | 75 | 76 | int main() { 77 | int ____localvar____7 = 1; 78 | while (____localvar____7 != 0) 79 | switch (int ____localvar____7 = 1) { 80 | case 1: 81 | { 82 | return 0; 83 | break; 84 | } 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /test/_anoyomous.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | struct { 5 | int a, b; 6 | } X, Y=X; 7 | return 0; 8 | } 9 | -------------------------------------------------------------------------------- /test/_array.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | void declref() { 7 | int a[][3][2] = { {1,2,3}, {}, {{3,},{9,8}} }; 8 | a[0][0][1] = 0; 9 | } 10 | 11 | void classref() { 12 | string b[][2] = { {},{"xx", string("yyy")} }; 13 | vector A; 14 | A[2][3] = 'x'; 15 | } 16 | 17 | int main() { 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /test/_badcase.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | int main() { 3 | if(int a = 0){ 4 | int b = 1; 5 | } else { 6 | int c = 2; 7 | } 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /test/_big.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | const int MAXN = 20000; 7 | const int INF = 1000000000; 8 | 9 | struct Edge 10 | { 11 | int v,cap; 12 | Edge *next,*pair; 13 | }edge[MAXN*22*2+10]; 14 | 15 | struct Graph 16 | { 17 | Edge *G[MAXN+10],*cur[MAXN+10],*pE; 18 | int dist[MAXN+10],num[MAXN+10]; 19 | int n,s,t; 20 | void init(int nn,int ss,int tt) 21 | { 22 | n=nn; 23 | s=ss,t=tt; 24 | memset(G,0,sizeof(G)); 25 | pE=edge; 26 | } 27 | void add(int u,int v,int cap,Edge *pair) 28 | { 29 | pE->v=v; 30 | pE->cap=cap; 31 | pE->next=G[u]; 32 | pE->pair=pair; 33 | G[u]=pE++; 34 | } 35 | void add(int u,int v,int cap) 36 | { 37 | add(u,v,cap,pE+1); 38 | add(v,u,0,pE-1); 39 | } 40 | int aug(int u,int preCap) 41 | { 42 | if(u==t)return preCap; 43 | int leftCap=preCap; 44 | for(Edge *&it=cur[u];it;it=it->next) 45 | { 46 | if(it->cap&&dist[it->v]+1==dist[u]) 47 | { 48 | int d=aug(it->v,min(leftCap,it->cap)); 49 | it->cap-=d; 50 | it->pair->cap+=d; 51 | leftCap-=d; 52 | if(leftCap==0||dist[s]==n)return preCap-leftCap; 53 | } 54 | } 55 | 56 | int minDist=n; 57 | for(Edge *it=cur[u]=G[u];it;it=it->next) 58 | if(it->cap)minDist=min(minDist,dist[it->v]+1);//+1 59 | if(--num[dist[u]]==0)dist[s]=n; 60 | else num[dist[u]=minDist]++; 61 | return preCap-leftCap; 62 | } 63 | int maxFlow() 64 | { 65 | memset(dist,0,sizeof(dist)); 66 | memset(num,0,sizeof(num)); 67 | memmove(cur,G,sizeof(G)); 68 | num[0]=n; 69 | int flow=0; 70 | while(dist[s] 2 | int multi_exit() { 3 | int a = 0; 4 | if(a){ 5 | return 1; 6 | } else if(a==0) { 7 | return 2; 8 | } else { 9 | return 3; 10 | } 11 | 12 | return 3; 13 | } 14 | int main(){ 15 | int a = 0; 16 | } 17 | 18 | void empty() {} 19 | 20 | void swi() { 21 | int a ; 22 | switch(a) { 23 | case 0: 24 | return; 25 | case 1: 26 | break; 27 | case 2: 28 | return; 29 | default: 30 | break; 31 | } 32 | return ; 33 | } 34 | -------------------------------------------------------------------------------- /test/_class.cpp: -------------------------------------------------------------------------------- 1 | template 2 | class A{ 3 | public: 4 | void func(T x); 5 | }; 6 | 7 | template 8 | void A::func(T x) { 9 | while(true){ 10 | do{}while(0); 11 | } 12 | } 13 | /* 14 | class B : public A{ 15 | public: 16 | 17 | }; 18 | void gf() { 19 | while(true) 20 | for(;;){} 21 | } 22 | 23 | */ 24 | int main() { 25 | A a; 26 | A b; 27 | class LOCAL { 28 | void func() { 29 | int x = 0; 30 | for(;;){} 31 | } 32 | }; 33 | LOCAL b; 34 | /* 35 | B b; 36 | b.func(b); 37 | class LOCAL{ 38 | int x; 39 | void func() { 40 | switch(int y = x){ 41 | while(true){ 42 | case 3: ; 43 | for(;;){ 44 | default: 45 | case 1: 46 | ;break; 47 | case 2: 48 | continue; 49 | do{ 50 | case 0: 51 | break; 52 | }while(y); 53 | break; 54 | } 55 | } 56 | } 57 | } 58 | }; 59 | class { 60 | int y; 61 | } anoy; 62 | 63 | */ 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /test/_cond.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int ifif() { 4 | int a, b, c, d, e; 5 | 6 | if( c,d,a || (b||e) || (c && d) || (~b)) { 7 | e = a, b, c; 8 | return 0; 9 | } 10 | return 2; 11 | } 12 | 13 | int main() { 14 | 15 | int a = 0; 16 | int b = (a) ? 1 : 0; 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /test/_const.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | //const array 6 | void const_initlist() { 7 | const char *p[] = { "a", "b" }; 8 | const char *aa = "xx"; 9 | char* const bb = "yy"; 10 | //char *p[] = { const_cast("a"), const_cast("b") }; 11 | } 12 | 13 | 14 | //const reference 15 | string gs; 16 | const string &func() { 17 | return gs; 18 | } 19 | 20 | int main() 21 | { 22 | const_initlist(); 23 | //const ptr using new 24 | int *cp = (int*)new const int(1024); 25 | printf("%d ", *cp); 26 | *cp = 20; 27 | printf("%d\n", *cp); 28 | 29 | //const returned by STL 30 | string str; 31 | char *pstr = (char*)str.c_str(); 32 | const string cstr = "xxxxxx"; 33 | pstr = (char*)cstr.c_str(); 34 | string *qstr = (string*)&func(); 35 | 36 | 37 | //reference has conversion 38 | string &f = const_cast(func()); 39 | string *pf = &(const_cast(func())); 40 | 41 | 42 | char *p = const_cast(&("haha")[0]); 43 | const char *q = &("haha")[0]; 44 | // FIXME const char array is not a init list?? 45 | char xx[];// = "hoho"; 46 | char *px = xx; 47 | px = &xx[0]; 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /test/_construct.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class A{ 4 | public: 5 | static int counter; 6 | A(){ 7 | printf("counter = %d\n", ++counter); 8 | } 9 | 10 | void C() const{ 11 | int* pc = &counter; 12 | *pc = 1; 13 | } 14 | }; 15 | int A::counter = 0; 16 | 17 | A ga; 18 | 19 | int main() 20 | { 21 | char *p = (char*)(&("haha")[0]); 22 | double val = 3.14; 23 | const int &rr = val; 24 | const int &yy = 2.234; 25 | int hh; 26 | int *pref = &(hh); 27 | hh = (*pref) = 32 + (*pref); 28 | typedef int MAT[2][2]; 29 | MAT a, b = a; 30 | //int *prr = (int*)&val; // ill 31 | //*(int*)rr = 2; 32 | printf("%lf %d\n", val, (*pref)); 33 | A la; 34 | la.C(); 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /test/_decl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | class CCC{ 7 | public: 8 | void ehaha() { 9 | static int fuck = 0; 10 | { 11 | int fuck = 1; 12 | } 13 | fuck++; 14 | } 15 | }; 16 | 17 | bool BOOL; 18 | int INT = 1, *PINT = &INT; 19 | string STR("xx"), *PSTR = &STR; 20 | 21 | template 22 | void tpl(T aa) { 23 | T yy = T(); 24 | T zz = T("yy"); 25 | yy = T(); 26 | yy = "yy"; 27 | } 28 | 29 | void assign() { 30 | int x; 31 | x = int(10); 32 | 33 | string uu = "yy"; 34 | string yy = string(); 35 | string zz = string("yy"); 36 | yy = string(); 37 | yy = string("yy"); 38 | yy = "yy"; 39 | 40 | uu = "yy", yy = "zz", zz = string(); 41 | } 42 | 43 | 44 | void externvar() { 45 | tpl("yy"); 46 | int INT = 2; 47 | { 48 | extern int INT; 49 | INT = 3; 50 | } 51 | {} 52 | } 53 | 54 | void arraytype(){ 55 | int n = 3; 56 | { 57 | typedef string stype; 58 | string str; 59 | stype ary; 60 | stype bry = ary; 61 | } 62 | { 63 | typedef int varray[n][n]; 64 | varray ary; 65 | } 66 | { 67 | int ary[] = {n, n*2}; 68 | printf("%d\n", ary[1]); 69 | } 70 | { 71 | int ary[3] = {3, n/2}; 72 | printf("%d\n", ary[1]); 73 | } 74 | { 75 | int ary[][2][3] = { 76 | { {111,112,113}, {121,122,123} }, 77 | { {211,212}, {221} }, 78 | {} 79 | }; 80 | printf("%d %d\n", ary[1][1][0], ary[2][1][2]); 81 | } 82 | { 83 | int ary[n][n*2]; 84 | } 85 | 86 | } 87 | 88 | void constvar() { 89 | int x = 1, y = 2; 90 | x = 2; 91 | const int *p = &x; 92 | p = &y; 93 | int* const q = &x; 94 | *q = 4; 95 | } 96 | 97 | void init() { 98 | int xx(0), yy = 0, zz[] = {xx, yy}; 99 | ({int xx(2); yy = 3;}); 100 | } 101 | 102 | void callfunc(string &ref, string *ptr) { 103 | int x = (ref.length(), ptr->length()); 104 | int y = (ref.length()+((*ptr).length() * ptr->length())) / 2; 105 | string rr = "test", ss("ttest"); 106 | string *rf; 107 | if(ref.c_str() == ptr->c_str() 108 | && (rr=ref).c_str() == (*ptr).c_str()){ 109 | string &f = *ptr; 110 | rf = &(*ptr); 111 | static int x, y = 3; 112 | printf("static %d\n", ++y + x); 113 | } 114 | 115 | void (*fp)(string &, string *) = callfunc; 116 | void (*&fpr)(string &, string *) = fp; 117 | void (**fpp)(string &, string *) = &(fp); 118 | printf("%u %u %u\n", (unsigned int)fp, (unsigned int)fpr, (unsigned int)(*fpp)); 119 | } 120 | 121 | int main() { 122 | string LSTR = STR; 123 | printf("%s\n", LSTR.c_str()); 124 | externvar(); 125 | callfunc(LSTR, &LSTR); 126 | return 0; 127 | } 128 | -------------------------------------------------------------------------------- /test/_des.cpp: -------------------------------------------------------------------------------- 1 | #ifndef _DES_ENCRYPT_DECRYPT 2 | #define _DES_ENCRYPT_DECRYPT 3 | 4 | #define BYTE unsigned char 5 | #define LPBYTE BYTE* 6 | #define LPCBYTE const BYTE* 7 | #define BOOL int 8 | 9 | class DES 10 | { 11 | public: 12 | BOOL CDesEnter(LPCBYTE in, LPBYTE out, int datalen, const BYTE key[8], BOOL type); 13 | BOOL CDesMac(LPCBYTE mac_data, LPBYTE mac_code, int datalen, const BYTE key[8]); 14 | private: 15 | void XOR(const BYTE in1[8], const BYTE in2[8], BYTE out[8]); 16 | LPBYTE Bin2ASCII(const BYTE byte[64], BYTE bit[8]); 17 | LPBYTE ASCII2Bin(const BYTE bit[8], BYTE byte[64]); 18 | void GenSubKey(const BYTE oldkey[8], BYTE newkey[16][8]); 19 | void endes(const BYTE m_bit[8], const BYTE k_bit[8], BYTE e_bit[8]); 20 | void undes(const BYTE m_bit[8], const BYTE k_bit[8], BYTE e_bit[8]); 21 | void SReplace(BYTE s_bit[8]); 22 | }; 23 | 24 | /* 25 | * CDesEnter 函数说明: 26 | * des加密/解密入口 27 | * 返回: 28 | * 1则成功,0失败 29 | * 参数: 30 | * in 需要加密或解密的数据 31 | * 注意:in缓冲区的大小必须和datalen相同. 32 | * out 加密后或解密后输出。 33 | * 注意:out缓冲区大小必须是8的倍数而且比datalen大或者相等。 34 | * 如datalen=7,out缓冲区的大小应该是8,datalen=8,out缓冲区的大小应该是8, 35 | * datalen=9,out缓冲区的大小应该是16,依此类推。 36 | * datalen 数据长度(字节)。 37 | * 注意:datalen 必须是8的倍数。 38 | * key 8个字节的加密或解密的密码。 39 | * type 是对数据进行加密还是解密 40 | * 0 表示加密 1 表示解密 41 | */ 42 | BOOL DES::CDesEnter(LPCBYTE in, LPBYTE out, int datalen, const BYTE key[8], BOOL type) 43 | { 44 | //判断输入参数是否正确,失败的情况为: 45 | //!in: in指针(输入缓冲)无效 46 | //!out: out指针(输出缓冲)无效 47 | //datalen<1: 数据长度不正确 48 | //!key: 加/解密密码无效 49 | //type && ((datalen % 8) !=0:选择解密方式但是输入密文不为8的倍数 50 | if((!in) || (!out) || (datalen<1) || (!key) || (type && ((datalen % 8) !=0))) 51 | return false; 52 | 53 | 54 | if(type==0) //选择的模式是加密 55 | { 56 | // 用于存储待加密字串最后的若干字节 57 | // DES算法是以8个字节为单位进行加密,如果待加密字串以8为单位分段加密时,最后一段不足 58 | //8字节,则在后面补0,使其最后一段的长度为8字节 59 | // te8bit是作为存储待加密字串最后一段(不足8字节)的变量 60 | BYTE te8bit[8]={0,0,0,0,0,0,0,0}; 61 | 62 | // 这是待加密字串的调整长度 63 | // 如果原始长度是8的整数倍,则调整长度的值和原来的长度一样 64 | // 如果原始长度不是8的整数倍,则调整长度的值是能被8整除且不大于原来长度的最大整数。 65 | //也就是不需要补齐的块的总长度。 66 | int te_fixlen = datalen - (datalen % 8); 67 | 68 | // 将待加密密文以8为单位分段,把最后长度不足8的一段存储到te8bit中。 69 | for(int i = 0; i < (datalen % 8); i++) 70 | te8bit[i] = in[te_fixlen + i]; 71 | 72 | // 将待加密字串分以8字节为单位分段加密 73 | for(int i = 0; i < te_fixlen; i += 8) 74 | endes(in + i, key, out + i); 75 | 76 | // 如果待加密字串不是8的整数倍,则将最后一段补齐(补0)后加密 77 | if(datalen % 8 != 0) 78 | endes(te8bit, key, out + datalen / 8 * 8); 79 | } 80 | else //选择的模式是解密 81 | { 82 | // 将密文以8字节为单位分段解密 83 | for(int i = 0; i < datalen; i += 8) 84 | undes(in + i, key, out + i); 85 | } 86 | return true; 87 | } 88 | 89 | /* 90 | * CDesMAC 函数说明: 91 | * DESMAC 数据验校 92 | * 返回: 93 | * 1则成功,0失败 94 | * 参数: 95 | * mac_data MAC验校数据 96 | * 注意:Mac_data缓冲区的大小(16字节以上)必须和datalen相同,而且应是8的倍数。 97 | * out_mac MAC验校输出(8字节) 98 | * dadalen 数据长度(字节)。 99 | * 注意:datalen 必须是16以上而且是8的倍数。 100 | * key 8个字节的验校密码。 101 | */ 102 | BOOL DES::CDesMac(LPCBYTE mac_data, LPBYTE mac_code, int datalen, const BYTE key[8]) 103 | { 104 | //判断输入参数是否正确,失败的情况为: 105 | //!mac_data: mac_data指针(输入缓冲)无效 106 | //!mac_code: mac_code指针(输出缓冲)无效 107 | //datalen<16: 数据长度不正确 108 | //datalen % 8 != 0: 数据长度不为8的整数倍 109 | //!key:密码不符合要求 110 | if((!mac_data) || (!mac_code) || (datalen < 16) || (datalen % 8 != 0) || (!key)) 111 | return false; 112 | endes(mac_data, key, mac_code); 113 | for(int i = 8; i < datalen; i += 8) 114 | { 115 | XOR(mac_code, mac_data + i, mac_code); 116 | endes(mac_code, key, mac_code); 117 | } 118 | return true; 119 | } 120 | 121 | /* 122 | * XOR 函数说明: 123 | * 将输入的两个8字节字符串异或 124 | * 返回: 125 | * 无 126 | * 参数: 127 | * const BYTE in1[8] 输入字符串1 128 | * const BYTE in2[8] 输入字符串2 129 | * BYTE out[8] 输出的结果字符串 130 | */ 131 | void DES::XOR(const BYTE in1[8], const BYTE in2[8], BYTE out[8]) 132 | { 133 | for(int i = 0; i < 8; i++) 134 | out[i] = in1[i] ^ in2[i]; 135 | } 136 | 137 | /* 138 | * Bin2ASCII 函数说明: 139 | * 将64字节的01字符串转换成对应的8个字节 140 | * 返回: 141 | * 转换后结果的指针 142 | * 参数: 143 | * const BYTE byte[64] 输入字符串 144 | * BYTE bit[8] 输出的转换结果 145 | */ 146 | LPBYTE DES::Bin2ASCII(const BYTE byte[64], BYTE bit[8]) 147 | { 148 | for(int i = 0; i < 8; i++) 149 | { 150 | bit[i] = byte[i * 8] * 128 + byte[i * 8 + 1] * 64 + 151 | byte[i * 8 + 2] * 32 + byte[i * 8 + 3] * 16 + 152 | byte[i * 8 + 4] * 8 + byte[i * 8 + 5] * 4 + 153 | byte[i * 8 + 6] * 2 + byte[i * 8 + 7]; 154 | } 155 | return bit; 156 | } 157 | 158 | /* 159 | * ASCII2Bin 函数说明: 160 | * 将8个字节输入转换成对应的64字节的01字符串 161 | * 返回: 162 | * 转换后结果的指针 163 | * 参数: 164 | * const BYTE bit[8] 输入字符串 165 | * BYTE byte[64] 输出的转换结果 166 | */ 167 | LPBYTE DES::ASCII2Bin(const BYTE bit[8], BYTE byte[64]) 168 | { 169 | for(int i=0; i < 8; i++) 170 | for(int j = 0; j < 8; j++) 171 | byte[i * 8 + j] = ( bit[i] >> (7 - j) ) & 0x01; 172 | return byte; 173 | } 174 | 175 | /* 176 | * GenSubKey 函数说明: 177 | * 由输入的密钥得到16个子密钥 178 | * 返回: 179 | * 无 180 | * 参数: 181 | * const BYTE oldkey[8] 输入密钥 182 | * BYTE newkey[16][8] 输出的子密钥 183 | */ 184 | void DES::GenSubKey(const BYTE oldkey[8], BYTE newkey[16][8]) 185 | { 186 | int i, k, rol = 0; 187 | 188 | //缩小换位表1 189 | int pc_1[56] = {57,49,41,33,25,17,9, 190 | 1,58,50,42,34,26,18, 191 | 10,2,59,51,43,35,27, 192 | 19,11,3,60,52,44,36, 193 | 63,55,47,39,31,23,15, 194 | 7,62,54,46,38,30,22, 195 | 14,6,61,53,45,37,29, 196 | 21,13,5,28,20,12,4}; 197 | //缩小换位表2 198 | int pc_2[48] = {14,17,11,24,1,5, 199 | 3,28,15,6,21,10, 200 | 23,19,12,4,26,8, 201 | 16,7,27,20,13,2, 202 | 41,52,31,37,47,55, 203 | 30,40,51,45,33,48, 204 | 44,49,39,56,34,53, 205 | 46,42,50,36,29,32}; 206 | //16次循环左移对应的左移位数 207 | int ccmovebit[16] = {1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1}; 208 | 209 | BYTE oldkey_byte[64]; 210 | BYTE oldkey_byte1[64]; 211 | BYTE oldkey_byte2[64]; 212 | BYTE oldkey_c[56]; 213 | BYTE oldkey_d[56]; 214 | BYTE newkey_byte[16][64]; 215 | 216 | ASCII2Bin(oldkey, oldkey_byte); 217 | 218 | //位变换 219 | for(i = 0; i < 56; i++) 220 | oldkey_byte1[i] = oldkey_byte[pc_1[i] - 1]; 221 | //分为左右两部分,复制一遍以便于循环左移 222 | for(i = 0; i < 28; i++) 223 | oldkey_c[i] = oldkey_byte1[i], oldkey_c[i + 28] = oldkey_byte1[i], 224 | oldkey_d[i] = oldkey_byte1[i + 28], oldkey_d[i + 28] = oldkey_byte1[i + 28]; 225 | 226 | //分别生成16个子密钥 227 | for(i = 0; i < 16; i++) 228 | { 229 | //循环左移 230 | rol += ccmovebit[i]; 231 | //合并左移后的结果 232 | for(k = 0; k < 28; k++) 233 | oldkey_byte2[k] = oldkey_c[k + rol], oldkey_byte2[k + 28] = oldkey_d[k + rol]; 234 | //位变换 235 | for(k = 0; k < 48; k++) 236 | newkey_byte[i][k] = oldkey_byte2[pc_2[k] - 1]; 237 | 238 | } 239 | //生成最终结果 240 | for(i = 0; i < 16; i++) 241 | Bin2ASCII(newkey_byte[i], newkey[i]); 242 | } 243 | 244 | /* 245 | * endes 函数说明: 246 | * DES加密 247 | * 返回: 248 | * 无 249 | * 参数: 250 | * const BYTE m_bit[8] 输入的原文 251 | * const BYTE k_bit[8] 输入的密钥 252 | * BYTE e_bit[8] 输出的密文 253 | */ 254 | void DES::endes(const BYTE m_bit[8], const BYTE k_bit[8], BYTE e_bit[8]) 255 | { 256 | //换位表IP 257 | int ip[64] = { 258 | 58,50,42,34,26,18,10,2, 259 | 60,52,44,36,28,20,12,4, 260 | 62,54,46,38,30,22,14,6, 261 | 64,56,48,40,32,24,16,8, 262 | 57,49,41,33,25,17,9,1, 263 | 59,51,43,35,27,19,11,3, 264 | 61,53,45,37,29,21,13,5, 265 | 63,55,47,39,31,23,15,7 266 | }; 267 | //换位表IP_1 268 | int ip_1[64] = { 269 | 40,8,48,16,56,24,64,32, 270 | 39,7,47,15,55,23,63,31, 271 | 38,6,46,14,54,22,62,30, 272 | 37,5,45,13,53,21,61,29, 273 | 36,4,44,12,52,20,60,28, 274 | 35,3,43,11,51,19,59,27, 275 | 34,2,42,10,50,18,58,26, 276 | 33,1,41,9,49,17,57,25 277 | }; 278 | //放大换位表 279 | int e[48] = { 280 | 32,1, 2, 3, 4, 5, 281 | 4, 5, 6, 7, 8, 9, 282 | 8, 9, 10,11,12,13, 283 | 12,13,14,15,16,17, 284 | 16,17,18,19,20,21, 285 | 20,21,22,23,24,25, 286 | 24,25,26,27,28,29, 287 | 28,29,30,31,32,1 288 | }; 289 | BYTE m_bit1[8] = {0}; 290 | BYTE m_byte[64] = {0}; 291 | BYTE m_byte1[64] = {0}; 292 | BYTE key_n[16][8] = {0}; 293 | BYTE l_bit[17][8] = {0}; 294 | BYTE r_bit[17][8] = {0}; 295 | BYTE e_byte[64] = {0}; 296 | BYTE e_byte1[64] = {0}; 297 | BYTE r_byte[64] = {0}; 298 | BYTE r_byte1[64] = {0}; 299 | int i, j; 300 | 301 | //根据密钥生成16个子密钥 302 | GenSubKey(k_bit, key_n); 303 | //将待加密字串变换成01串 304 | ASCII2Bin(m_bit, m_byte); 305 | //按照ip表对待加密字串进行位变换 306 | for(i = 0; i < 64; i++) 307 | m_byte1[i] = m_byte[ip[i] - 1]; 308 | //位变换后的待加密字串 309 | Bin2ASCII(m_byte1, m_bit1); 310 | //将位变换后的待加密字串分成两组,分别为前4字节L和后4字节R,作为迭代的基础(第0次迭代) 311 | for(i = 0; i < 4; i++) 312 | l_bit[0][i] = m_bit1[i], r_bit[0][i] = m_bit1[i + 4]; 313 | 314 | //16次迭代运算 315 | for(i = 1; i <= 16; i++) 316 | { 317 | //R的上一次的迭代结果作为L的当前次迭代结果 318 | for(j = 0; j < 4; j++) 319 | l_bit[i][j] = r_bit[i-1][j]; 320 | 321 | ASCII2Bin(r_bit[i-1], r_byte); 322 | //将R的上一次迭代结果按E表进行位扩展得到48位中间结果 323 | for(j = 0; j < 48; j++) 324 | r_byte1[j] = r_byte[e[j] - 1]; 325 | Bin2ASCII(r_byte1, r_bit[i-1]); 326 | 327 | //与第I-1个子密钥进行异或运算 328 | for(j = 0; j < 6; j++) 329 | r_bit[i-1][j] = r_bit[i-1][j] ^ key_n[i-1][j]; 330 | 331 | //进行S选择,得到32位中间结果 332 | SReplace(r_bit[i - 1]); 333 | 334 | //结果与L的上次迭代结果异或得到R的此次迭代结果 335 | for(j = 0; j < 4; j++) 336 | { 337 | r_bit[i][j] = l_bit[i-1][j] ^ r_bit[i-1][j]; 338 | } 339 | } 340 | //组合最终迭代结果 341 | for(i = 0; i < 4; i++) 342 | e_bit[i] = r_bit[16][i], e_bit[i + 4] = l_bit[16][i]; 343 | 344 | ASCII2Bin(e_bit, e_byte); 345 | //按照表IP-1进行位变换 346 | for(i = 0; i < 64; i++) 347 | e_byte1[i] = e_byte[ip_1[i] - 1]; 348 | //得到最后的加密结果 349 | Bin2ASCII(e_byte1, e_bit); 350 | } 351 | 352 | /* 353 | * undes 函数说明: 354 | * DES解密,与加密步骤完全相同,只是迭代顺序是从16到1 355 | * 返回: 356 | * 无 357 | * 参数: 358 | * const BYTE m_bit[8] 输入的密文 359 | * const BYTE k_bit[8] 输入的密钥 360 | * BYTE e_bit[8] 输出解密后的原文 361 | */ 362 | void DES::undes(const BYTE m_bit[8], const BYTE k_bit[8], BYTE e_bit[8]) 363 | { 364 | //换位表IP 365 | int ip[64] = { 366 | 58,50,42,34,26,18,10,2, 367 | 60,52,44,36,28,20,12,4, 368 | 62,54,46,38,30,22,14,6, 369 | 64,56,48,40,32,24,16,8, 370 | 57,49,41,33,25,17,9,1, 371 | 59,51,43,35,27,19,11,3, 372 | 61,53,45,37,29,21,13,5, 373 | 63,55,47,39,31,23,15,7 374 | }; 375 | //换位表IP_1 376 | int ip_1[64] = { 377 | 40,8,48,16,56,24,64,32, 378 | 39,7,47,15,55,23,63,31, 379 | 38,6,46,14,54,22,62,30, 380 | 37,5,45,13,53,21,61,29, 381 | 36,4,44,12,52,20,60,28, 382 | 35,3,43,11,51,19,59,27, 383 | 34,2,42,10,50,18,58,26, 384 | 33,1,41,9,49,17,57,25 385 | }; 386 | //放大换位表 387 | int e[48] = { 388 | 32,1, 2, 3, 4, 5, 389 | 4, 5, 6, 7, 8, 9, 390 | 8, 9, 10,11,12,13, 391 | 12,13,14,15,16,17, 392 | 16,17,18,19,20,21, 393 | 20,21,22,23,24,25, 394 | 24,25,26,27,28,29, 395 | 28,29,30,31,32,1 396 | }; 397 | BYTE m_bit1[8] = {0}; 398 | BYTE m_byte[64] = {0}; 399 | BYTE m_byte1[64] = {0}; 400 | BYTE key_n[16][8] = {0}; 401 | BYTE l_bit[17][8] = {0}; 402 | BYTE r_bit[17][8] = {0}; 403 | BYTE e_byte[64] = {0}; 404 | BYTE e_byte1[64] = {0}; 405 | BYTE l_byte[64] = {0}; 406 | BYTE l_byte1[64] = {0}; 407 | int i = 0, j = 0; 408 | 409 | //根据密钥生成16个子密钥 410 | GenSubKey(k_bit, key_n); 411 | //将待加密字串变换成01串 412 | ASCII2Bin(m_bit, m_byte); 413 | //按照ip表对待加密字串进行位变换 414 | for(i = 0; i < 64; i++) 415 | m_byte1[i] = m_byte[ip[i] - 1]; 416 | //位变换后的待加密字串 417 | Bin2ASCII(m_byte1, m_bit1); 418 | //将位变换后的待加密字串分成两组,分别为前4字节R和后4字节L,作为迭代的基础(第16次迭代) 419 | for(i = 0; i < 4; i++) 420 | r_bit[16][i] = m_bit1[i], l_bit[16][i] = m_bit1[i + 4]; 421 | 422 | //16次迭代运算 423 | for(i = 16; i > 0; i--) 424 | { 425 | //L的上一次的迭代结果作为R的当前次迭代结果 426 | for(j = 0; j < 4; j++) 427 | r_bit[i-1][j] = l_bit[i][j]; 428 | 429 | ASCII2Bin(l_bit[i], l_byte); 430 | //将L的上一次迭代结果按E表进行位扩展得到48位中间结果 431 | for(j = 0; j < 48; j++) 432 | l_byte1[j] = l_byte[e[j] - 1]; 433 | Bin2ASCII(l_byte1, l_bit[i]); 434 | 435 | //与第I-1个子密钥进行异或运算 436 | for(j = 0; j < 6; j++) 437 | l_bit[i][j] = l_bit[i][j] ^ key_n[i-1][j]; 438 | 439 | //进行S选择,得到32位中间结果 440 | SReplace(l_bit[i]); 441 | 442 | //结果与R的上次迭代结果异或得到L的此次迭代结果 443 | for(j = 0; j < 4; j++) 444 | { 445 | l_bit[i-1][j] = r_bit[i][j] ^ l_bit[i][j]; 446 | } 447 | } 448 | //组合最终迭代结果 449 | for(i = 0; i < 4; i++) 450 | e_bit[i] = l_bit[0][i], e_bit[i + 4] = r_bit[0][i]; 451 | 452 | ASCII2Bin(e_bit, e_byte); 453 | //按照表IP-1进行位变换 454 | for(i = 0; i < 64; i++) 455 | e_byte1[i] = e_byte[ip_1[i] - 1]; 456 | //得到最后的结果 457 | Bin2ASCII(e_byte1, e_bit); 458 | } 459 | 460 | /* 461 | * SReplace 函数说明: 462 | * S选择 463 | * 返回: 464 | * 无 465 | * 参数: 466 | * BYTE s_bit[8] 输入暨选择后的输出 467 | */ 468 | void DES::SReplace(BYTE s_bit[8]) 469 | { 470 | int p[32] = { 471 | 16,7,20,21, 472 | 29,12,28,17, 473 | 1,15,23,26, 474 | 5,18,31,10, 475 | 2,8,24,14, 476 | 32,27,3,9, 477 | 19,13,30,6, 478 | 22,11,4,25 479 | }; 480 | BYTE s[][4][16] ={ 481 | { 482 | 14,4,13,1,2,15,11,8,3,10,6,12,5,9,0,7, 483 | 0,15,7,4,14,2,13,1,10,6,12,11,9,5,3,8, 484 | 4,1,14,8,13,6,2,11,15,12,9,7,3,10,5,0, 485 | 15,12,8,2,4,9,1,7,5,11,3,14,10,0,6,13 486 | }, 487 | { 488 | 15,1,8,14,6,11,3,4,9,7,2,13,12,0,5,10, 489 | 3,13,4,7,15,2,8,14,12,0,1,10,6,9,11,5, 490 | 0,14,7,11,10,4,13,1,5,8,12,6,9,3,2,15, 491 | 13,8,10,1,3,15,4,2,11,6,7,12,0,5,14,9 492 | }, 493 | { 494 | 10,0,9,14,6,3,15,5,1,13,12,7,11,4,2,8, 495 | 13,7,0,9,3,4,6,10,2,8,5,14,12,11,15,1, 496 | 13,6,4,9,8,15,3,0,11,1,2,12,5,10,14,7, 497 | 1,10,13,0,6,9,8,7,4,15,14,3,11,5,2,12 498 | }, 499 | { 500 | 7,13,14,3,0,6,9,10,1,2,8,5,11,12,4,15, 501 | 13,8,11,5,6,15,0,3,4,7,2,12,1,10,14,9, 502 | 10,6,9,0,12,11,7,13,15,1,3,14,5,2,8,4, 503 | 3,15,0,6,10,1,13,8,9,4,5,11,12,7,2,14 504 | }, 505 | { 506 | 2,12,4,1,7,10,11,6,8,5,3,15,13,0,14,9, 507 | 14,11,2,12,4,7,13,1,5,0,15,10,3,9,8,6, 508 | 4,2,1,11,10,13,7,8,15,9,12,5,6,3,0,14, 509 | 11,8,12,7,1,14,2,13,6,15,0,9,10,4,5,3, 510 | }, 511 | { 512 | 12,1,10,15,9,2,6,8,0,13,3,4,14,7,5,11, 513 | 10,15,4,2,7,12,9,5,6,1,13,14,0,11,3,8, 514 | 9,14,15,5,2,8,12,3,7,0,4,10,1,13,11,6, 515 | 4,3,2,12,9,5,15,10,11,14,1,7,6,0,8,13 516 | }, 517 | { 518 | 4,11,2,14,15,0,8,13,3,12,9,7,5,10,6,1, 519 | 13,0,11,7,4,9,1,10,14,3,5,12,2,15,8,6, 520 | 1,4,11,13,12,3,7,14,10,15,6,8,0,5,9,2, 521 | 6,11,13,8,1,4,10,7,9,5,0,15,14,2,3,12 522 | }, 523 | { 524 | 13,2,8,4,6,15,11,1,10,9,3,14,5,0,12,7, 525 | 1,15,13,8,10,3,7,4,12,5,6,11,0,14,9,2, 526 | 7,11,4,1,9,12,14,2,0,6,10,13,15,3,5,8, 527 | 2,1,14,7,4,10,8,13,15,12,9,0,3,5,6,11 528 | } 529 | }; 530 | BYTE s_byte[64] = {0}; 531 | BYTE s_byte1[64] = {0}; 532 | BYTE row = 0, col = 0; 533 | BYTE s_out_bit[8] = {0}; 534 | 535 | //转成二进制字符串处理 536 | ASCII2Bin(s_bit, s_byte); 537 | for(int i = 0; i < 8; i++) 538 | { 539 | //0、5位为row,1、2、3、4位为col,在S表中选择一个八位的数 540 | row = s_byte[i * 6] * 2 + s_byte[i * 6 + 5]; 541 | col = s_byte[i * 6 + 1] * 8 + s_byte[i * 6 + 2] * 4 + s_byte[i * 6 + 3] * 2 + s_byte[i * 6 + 4]; 542 | s_out_bit[i] = s[i][row][col]; 543 | } 544 | //将八个选择的八位数据压缩表示 545 | s_out_bit[0] = (s_out_bit[0] << 4) + s_out_bit[1]; 546 | s_out_bit[1] = (s_out_bit[2] << 4) + s_out_bit[3]; 547 | s_out_bit[2] = (s_out_bit[4] << 4) + s_out_bit[5]; 548 | s_out_bit[3] = (s_out_bit[6] << 4) + s_out_bit[7]; 549 | //转成二进制字符串处理 550 | ASCII2Bin(s_out_bit, s_byte); 551 | //换位 552 | for(int i = 0; i < 32; i++) 553 | s_byte1[i] = s_byte[p[i] - 1]; 554 | //生成最后结果 555 | Bin2ASCII(s_byte1, s_bit); 556 | } 557 | 558 | #endif 559 | 560 | int main() { 561 | return 0; 562 | } 563 | -------------------------------------------------------------------------------- /test/_do.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int x = 1; 5 | do { 6 | int y = 2; 7 | } while(y); //y not in scope 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /test/_enum.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | enum BOX{a,b,c}; 5 | enum {p,q} eee = p, fff(q); 6 | { 7 | enum CAT{d,a,b,c}; 8 | int x = a+b+d+p; 9 | } 10 | BOX z = a; 11 | BOX *s = &z; 12 | //eee = p; 13 | //z = BOX::a; 14 | //int zz = BOX::a; 15 | return 0; 16 | }; 17 | -------------------------------------------------------------------------------- /test/_for.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) 4 | { 5 | for(int i = 0; i < 13 && i > -1 || i < 14; i++){ 6 | LABEL0: 7 | { 8 | --i; 9 | LABEL1: 10 | { 11 | ----i; 12 | LABEL2: 13 | ++++++i; 14 | } 15 | } 16 | if (i > 9) { 17 | break; 18 | } else if (i, i+1, i-1, i-3) { 19 | i += 2; 20 | continue; 21 | } else { 22 | i = i+1-1+1-1; 23 | i *= 1; 24 | } 25 | } 26 | return 0; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /test/_function.cpp: -------------------------------------------------------------------------------- 1 | int parm_fun(int par1, int par2 = 0) { 2 | return par1 + par2; 3 | } 4 | 5 | int pow() { 6 | int a = 0; 7 | //pow(); 8 | a += pow(); 9 | { 10 | int b = 1; 11 | a += b, b += a, b += b; 12 | } 13 | return a; 14 | } 15 | 16 | int main() {return 0;} 17 | -------------------------------------------------------------------------------- /test/_gcd.cpp: -------------------------------------------------------------------------------- 1 | double fast_pow(double x, int n) { 2 | if (n == 0) 3 | return 1; 4 | double y = fast_pow(x, n/2); 5 | if (n%2 == 0) 6 | return y*y; 7 | else 8 | return y*y*x; 9 | } 10 | 11 | int main() { 12 | fast_pow(2.5, 50); 13 | return 0; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /test/_gcd_ob.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double fast_pow(double _var_0, int _var_1) { 4 | double _var_2; 5 | int _var_3 = 5; 6 | while (_var_3 != 0) 7 | switch (_var_3) { 8 | case 1: 9 | { 10 | return _var_2 * _var_2 * _var_0; 11 | } 12 | case 2: 13 | { 14 | return _var_2 * _var_2; 15 | } 16 | case 3: 17 | { 18 | _var_2 = fast_pow(_var_0, _var_1 / 2); 19 | if (_var_1 % 2 == 0) { 20 | _var_3 = 2; 21 | } else { 22 | _var_3 = 1; 23 | } 24 | break; 25 | } 26 | case 4: 27 | { 28 | return 1; 29 | } 30 | case 5: 31 | { 32 | if (_var_1 == 0) { 33 | _var_3 = 4; 34 | } else { 35 | _var_3 = 3; 36 | } 37 | break; 38 | } 39 | } 40 | } 41 | 42 | 43 | int main() { 44 | int _var_4 = 1; 45 | while (_var_4 != 0) 46 | switch (int _var_4 = 1) { 47 | case 1: 48 | { 49 | std::cout << fast_pow(2, 17) << std::endl; 50 | return 0; 51 | } 52 | } 53 | } 54 | 55 | 56 | -------------------------------------------------------------------------------- /test/_getcfg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [ $# -ne 1 ]; then 3 | exit 1; 4 | fi 5 | #dot $1 -Tpng -o _tmp.png && sz -y _tmp.png 6 | dot $1 -Tpng -o _tmp.png 7 | -------------------------------------------------------------------------------- /test/_goto.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | void *addr[] = {&&LBL0, &&LBL1, &&LBL2}; 5 | int a = 0, b = 1, c = 2; 6 | goto *addr[1]; 7 | LBL0: 8 | goto *addr[1]; 9 | LBL1: 10 | goto *addr[2]; 11 | LBL2: 12 | goto *addr[0]; 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /test/_hdu3589.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | int MIN(int a,int b) { if( ab ) return a; else return b; } 8 | #define CLR(NAME,VALUE) memset(NAME,VALUE,sizeof(NAME)) 9 | using namespace std; 10 | typedef long long LL; 11 | const int MAXPRI=1000000+10; 12 | bool isNotPri[MAXPRI]; 13 | int priList[MAXPRI],priNum; 14 | void CalPri() { //线性筛法 15 | int i,j; 16 | memset(isNotPri,0,sizeof(isNotPri)); 17 | isNotPri[0]=isNotPri[1]=1; 18 | for(i=4;i ____localvar____4) { 49 | ____localvar____5 = 2; 50 | } else { 51 | ____localvar____5 = 1; 52 | } 53 | break; 54 | } 55 | } 56 | } 57 | 58 | ; 59 | using namespace std; 60 | typedef long long LL; 61 | const int MAXPRI = 1000000 + 10; 62 | bool isNotPri[1000010]; 63 | int priList[1000010]; 64 | int priNum; 65 | void CalPri() { 66 | int ____localvar____6; 67 | int ____localvar____7; 68 | int ____localvar____8 = 20; 69 | while (____localvar____8 != 0) 70 | switch (____localvar____8) { 71 | case 1: 72 | { 73 | ____label____11: 74 | ; 75 | ____localvar____8 = 0; 76 | break; 77 | } 78 | case 2: 79 | { 80 | ____label____10: 81 | ; 82 | ____localvar____6 += 2; 83 | ____localvar____8 = 13; 84 | break; 85 | } 86 | case 3: 87 | { 88 | ____label____7: 89 | ; 90 | ____localvar____8 = 2; 91 | break; 92 | } 93 | case 4: 94 | { 95 | ____label____6: 96 | ; 97 | ++____localvar____7; 98 | ____localvar____8 = 8; 99 | break; 100 | } 101 | case 5: 102 | { 103 | ____localvar____8 = 3; 104 | break; 105 | } 106 | case 6: 107 | { 108 | isNotPri[____localvar____6 * priList[____localvar____7]] = 1; 109 | if (____localvar____6 % priList[____localvar____7] == 0) { 110 | ____localvar____8 = 5; 111 | } else { 112 | ____localvar____8 = 4; 113 | } 114 | break; 115 | } 116 | case 7: 117 | { 118 | if (____localvar____7 < priNum && ____localvar____6 * priList[____localvar____7] < MAXPRI) { 119 | ____localvar____8 = 6; 120 | } else { 121 | ____localvar____8 = 3; 122 | } 123 | break; 124 | } 125 | case 8: 126 | { 127 | ____label____5: 128 | ; 129 | if (____localvar____7 < priNum) { 130 | ____localvar____8 = 9; 131 | } else { 132 | ____localvar____8 = 7; 133 | } 134 | break; 135 | } 136 | case 9: 137 | { 138 | ____localvar____6 * priList[____localvar____7] < MAXPRI; 139 | ____localvar____8 = 7; 140 | break; 141 | } 142 | case 10: 143 | { 144 | ____label____4: 145 | ; 146 | ____localvar____7 = 0; 147 | ____localvar____8 = 8; 148 | break; 149 | } 150 | case 11: 151 | { 152 | priList[priNum++] = ____localvar____6; 153 | ____localvar____8 = 10; 154 | break; 155 | } 156 | case 12: 157 | { 158 | if (!isNotPri[____localvar____6]) { 159 | ____localvar____8 = 11; 160 | } else { 161 | ____localvar____8 = 10; 162 | } 163 | break; 164 | } 165 | case 13: 166 | { 167 | ____label____9: 168 | ; 169 | if (____localvar____6 < MAXPRI) { 170 | ____localvar____8 = 12; 171 | } else { 172 | ____localvar____8 = 1; 173 | } 174 | break; 175 | } 176 | case 14: 177 | { 178 | ____label____8: 179 | ; 180 | ____localvar____6 = 3; 181 | ____localvar____8 = 13; 182 | break; 183 | } 184 | case 15: 185 | { 186 | ____label____3: 187 | ; 188 | priNum = 0; 189 | ____localvar____8 = 14; 190 | break; 191 | } 192 | case 16: 193 | { 194 | ____label____2: 195 | ; 196 | ____localvar____6 += 2; 197 | ____localvar____8 = 18; 198 | break; 199 | } 200 | case 17: 201 | { 202 | isNotPri[____localvar____6] = 1; 203 | ____localvar____8 = 16; 204 | break; 205 | } 206 | case 18: 207 | { 208 | ____label____1: 209 | ; 210 | if (____localvar____6 < MAXPRI) { 211 | ____localvar____8 = 17; 212 | } else { 213 | ____localvar____8 = 15; 214 | } 215 | break; 216 | } 217 | case 19: 218 | { 219 | ____label____0: 220 | ; 221 | ____localvar____6 = 4; 222 | ____localvar____8 = 18; 223 | break; 224 | } 225 | case 20: 226 | { 227 | memset(isNotPri, 0, sizeof (isNotPri)); 228 | isNotPri[0] = isNotPri[1] = 1; 229 | ____localvar____8 = 19; 230 | break; 231 | } 232 | } 233 | } 234 | 235 | ; 236 | LL MyPow(LL ____localvar____9, LL ____localvar____10, LL ____localvar____11) { 237 | LL ____localvar____12; 238 | int ____localvar____13 = 7; 239 | while (____localvar____13 != 0) 240 | switch (____localvar____13) { 241 | case 1: 242 | { 243 | return (____localvar____12 * ____localvar____12) % ____localvar____11; 244 | ____localvar____13 = 0; 245 | break; 246 | } 247 | case 2: 248 | { 249 | return ((____localvar____12 * ____localvar____12) % ____localvar____11) * ____localvar____9 % ____localvar____11; 250 | ____localvar____13 = 0; 251 | break; 252 | } 253 | case 3: 254 | { 255 | MyPow(____localvar____9, ____localvar____10 / 2, ____localvar____11); 256 | ____localvar____12 = MyPow(____localvar____9, ____localvar____10 / 2, ____localvar____11); 257 | if (____localvar____10 & 1) { 258 | ____localvar____13 = 2; 259 | } else { 260 | ____localvar____13 = 1; 261 | } 262 | break; 263 | } 264 | case 4: 265 | { 266 | return ____localvar____9 % ____localvar____11; 267 | ____localvar____13 = 0; 268 | break; 269 | } 270 | case 5: 271 | { 272 | if (____localvar____10 == 1) { 273 | ____localvar____13 = 4; 274 | } else { 275 | ____localvar____13 = 3; 276 | } 277 | break; 278 | } 279 | case 6: 280 | { 281 | return 1; 282 | ____localvar____13 = 0; 283 | break; 284 | } 285 | case 7: 286 | { 287 | if (____localvar____10 == 0) { 288 | ____localvar____13 = 6; 289 | } else { 290 | ____localvar____13 = 5; 291 | } 292 | break; 293 | } 294 | } 295 | } 296 | 297 | ; 298 | int Cal(int ____localvar____14, int ____localvar____15) { 299 | LL ____localvar____16; 300 | int ____localvar____17 = 5; 301 | while (____localvar____17 != 0) 302 | switch (____localvar____17) { 303 | case 1: 304 | { 305 | return -1; 306 | ____localvar____17 = 0; 307 | break; 308 | } 309 | case 2: 310 | { 311 | return 1; 312 | ____localvar____17 = 0; 313 | break; 314 | } 315 | case 3: 316 | { 317 | MyPow(____localvar____14, (____localvar____15 - 1) / 2, ____localvar____15); 318 | ____localvar____16 = MyPow(____localvar____14, (____localvar____15 - 1) / 2, ____localvar____15); 319 | if (____localvar____16 == 1 % ____localvar____15) { 320 | ____localvar____17 = 2; 321 | } else { 322 | ____localvar____17 = 1; 323 | } 324 | break; 325 | } 326 | case 4: 327 | { 328 | return 0; 329 | ____localvar____17 = 0; 330 | break; 331 | } 332 | case 5: 333 | { 334 | if (____localvar____14 % ____localvar____15 == 0 % ____localvar____15) { 335 | ____localvar____17 = 4; 336 | } else { 337 | ____localvar____17 = 3; 338 | } 339 | break; 340 | } 341 | } 342 | } 343 | 344 | ; 345 | int main() { 346 | int ____localvar____18; 347 | int ____localvar____19; 348 | int ____localvar____20; 349 | int ____localvar____21; 350 | int ____localvar____22; 351 | int ____localvar____23; 352 | int ____localvar____24 = 19; 353 | while (____localvar____24 != 0) 354 | switch (____localvar____24) { 355 | case 1: 356 | { 357 | ____label____20: 358 | ; 359 | return 0; 360 | ____localvar____24 = 0; 361 | break; 362 | } 363 | case 2: 364 | { 365 | ____label____19: 366 | ; 367 | ____localvar____24 = 18; 368 | break; 369 | } 370 | case 3: 371 | { 372 | printf("%d\n", ____localvar____21); 373 | ____localvar____24 = 2; 374 | break; 375 | } 376 | case 4: 377 | { 378 | Cal(____localvar____18, ____localvar____19); 379 | ____localvar____21 = Cal(____localvar____18, ____localvar____19); 380 | ____localvar____24 = 3; 381 | break; 382 | } 383 | case 5: 384 | { 385 | ____label____17: 386 | ; 387 | ____localvar____24 = 3; 388 | break; 389 | } 390 | case 6: 391 | { 392 | ____label____16: 393 | ; 394 | ____localvar____24 = 15; 395 | break; 396 | } 397 | case 7: 398 | { 399 | Cal(____localvar____18, priList[____localvar____22 - 1]); 400 | ____localvar____23 = Cal(____localvar____18, priList[____localvar____22 - 1]); 401 | pow((double)____localvar____23, ____localvar____20); 402 | ____localvar____21 *= pow((double)____localvar____23, ____localvar____20); 403 | ____localvar____24 = 6; 404 | break; 405 | } 406 | case 8: 407 | { 408 | ____label____14: 409 | ; 410 | ++____localvar____22; 411 | if (____localvar____20 != 0) { 412 | ____localvar____24 = 7; 413 | } else { 414 | ____localvar____24 = 6; 415 | } 416 | break; 417 | } 418 | case 9: 419 | { 420 | ____label____13: 421 | ; 422 | ____localvar____24 = 12; 423 | break; 424 | } 425 | case 10: 426 | { 427 | ____localvar____19 /= priList[____localvar____22]; 428 | ++____localvar____20; 429 | ____localvar____24 = 9; 430 | break; 431 | } 432 | case 11: 433 | { 434 | if (____localvar____19 % priList[____localvar____22] == 0 && ____localvar____19 != 1) { 435 | ____localvar____24 = 10; 436 | } else { 437 | ____localvar____24 = 8; 438 | } 439 | break; 440 | } 441 | case 12: 442 | { 443 | ____label____12: 444 | ; 445 | if (____localvar____19 % priList[____localvar____22] == 0) { 446 | ____localvar____24 = 13; 447 | } else { 448 | ____localvar____24 = 11; 449 | } 450 | break; 451 | } 452 | case 13: 453 | { 454 | ____localvar____19 != 1; 455 | ____localvar____24 = 11; 456 | break; 457 | } 458 | case 14: 459 | { 460 | ____localvar____20 = 0; 461 | ____localvar____24 = 12; 462 | break; 463 | } 464 | case 15: 465 | { 466 | ____label____15: 467 | ; 468 | if (____localvar____19 != 1) { 469 | ____localvar____24 = 14; 470 | } else { 471 | ____localvar____24 = 5; 472 | } 473 | break; 474 | } 475 | case 16: 476 | { 477 | ____localvar____22 = 0; 478 | ____localvar____24 = 15; 479 | break; 480 | } 481 | case 17: 482 | { 483 | ____localvar____21 = 1; 484 | if (isNotPri[____localvar____19]) { 485 | ____localvar____24 = 16; 486 | } else { 487 | ____localvar____24 = 4; 488 | } 489 | break; 490 | } 491 | case 18: 492 | { 493 | ____label____18: 494 | ; 495 | scanf("%d%d", &____localvar____18, &____localvar____19); 496 | if (scanf("%d%d", &____localvar____18, &____localvar____19) != (-1)) { 497 | ____localvar____24 = 17; 498 | } else { 499 | ____localvar____24 = 1; 500 | } 501 | break; 502 | } 503 | case 19: 504 | { 505 | CalPri(); 506 | ____localvar____24 = 18; 507 | break; 508 | } 509 | } 510 | } 511 | 512 | ; 513 | -------------------------------------------------------------------------------- /test/_hdu4121.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | using namespace std; 7 | char map[11][11]; 8 | const int dir[4][2] = {0,1,1,0,-1,0,0,-1}; 9 | int note[10][2]; 10 | int cnt; 11 | int b_x, b_y; 12 | 13 | bool law_G(int x, int y) 14 | { 15 | return x<=3 && x>=1 && y<=6 && y>=4; 16 | } 17 | 18 | bool deal_G(int x, int y, int n_x, int n_y) 19 | { 20 | if (n_y != y)return false; 21 | while (--x >= 1){ 22 | if (x == n_x)return true; 23 | if (map[x][y] == '.'){ 24 | continue; 25 | } else{ 26 | return false; 27 | } 28 | } 29 | return false; 30 | } 31 | 32 | bool check_right(int x, int y, int n_y) 33 | { 34 | for (int i(y+1); i<=9; ++i){ 35 | if (i == n_y)return true; 36 | if (map[x][i] == '.'){ 37 | continue; 38 | } else{ 39 | return false; 40 | } 41 | } 42 | return false; 43 | } 44 | 45 | bool check_left(int x,int y, int n_y) 46 | { 47 | for (int i(y-1); i>=1; --i){ 48 | if (i == n_y)return true; 49 | if (map[x][i] == '.'){ 50 | continue; 51 | } else{ 52 | return false; 53 | } 54 | } 55 | return false; 56 | } 57 | 58 | bool check_up(int x, int y,int n_x) 59 | { 60 | for (int i(x-1); i>=1; --i){ 61 | if (i == n_x)return true; 62 | if (map[i][y] == '.'){ 63 | continue; 64 | } else{ 65 | return false; 66 | } 67 | } 68 | return false; 69 | } 70 | 71 | bool check_down(int x, int y, int n_x) 72 | { 73 | for (int i(x+1); i<=10; ++i){ 74 | if (i == n_x)return true; 75 | if (map[i][y] == '.'){ 76 | continue; 77 | } else{ 78 | return false; 79 | } 80 | } 81 | return false; 82 | } 83 | 84 | bool deal_R(int x, int y, int n_x, int n_y) 85 | { 86 | if (x != n_x && y != n_y)return false; 87 | if (x == n_x){ 88 | if (y < n_y){ 89 | if (check_right(x,y,n_y))return true; 90 | return false; 91 | } else{ 92 | if (check_left(x,y,n_y))return true; 93 | return false; 94 | } 95 | } else{ 96 | if (x < n_x){ 97 | if (check_down(x,y,n_x))return true; 98 | return false; 99 | } else{ 100 | if (check_up(x,y,n_x))return true; 101 | return false; 102 | } 103 | } 104 | } 105 | 106 | bool deal_C(int x, int y, int n_x, int n_y) 107 | { 108 | bool flag = false; 109 | if (x != n_x && y != n_y)return false; 110 | if (x == n_x){ 111 | if (y < n_y){ 112 | while (++y < n_y){ 113 | if (map[x][y] == '.'){ 114 | continue; 115 | } else{ 116 | flag = true; 117 | break; 118 | } 119 | } 120 | if (flag){ 121 | if (check_right(x,y,n_y))return true; 122 | } 123 | } else{ 124 | while (--y > n_y){ 125 | if (map[x][y] == '.'){ 126 | continue; 127 | } else{ 128 | flag = true; 129 | break; 130 | } 131 | } 132 | if (flag){ 133 | if (check_left(x,y,n_y))return true; 134 | } 135 | } 136 | } else{ 137 | if (x < n_x){ 138 | while (++x < n_x){ 139 | if (map[x][y] == '.'){ 140 | continue; 141 | } else{ 142 | flag = true; 143 | break; 144 | } 145 | } 146 | if (flag){ 147 | if (check_down(x,y,n_x))return true; 148 | } 149 | } else{ 150 | while (--x > n_x){ 151 | if (map[x][y] == '.'){ 152 | continue; 153 | } else{ 154 | flag = true; 155 | break; 156 | } 157 | } 158 | if (flag){ 159 | if (check_up(x,y,n_x))return true; 160 | } 161 | } 162 | } 163 | return false; 164 | } 165 | 166 | bool deal_H(int x, int y, int n_x, int n_y){ 167 | if (x+2 == n_x && (y-1 == n_y || y+1 == n_y)){ 168 | if (map[x+1][y] == '.')return true; 169 | return false; 170 | } else{ 171 | if (x-2 == n_x && (y-1 == n_y || y+1 == n_y)){ 172 | if (map[x-1][y] == '.')return true; 173 | return false; 174 | } else{ 175 | if (y+2 == n_y && (x-1 == n_x || x+1 == n_x)){ 176 | if (map[x][y+1] == '.')return true; 177 | return false; 178 | } else{ 179 | if (y-2 == n_y && (x-1 == n_x || x+1 == n_x)){ 180 | if (map[x][y-1] == '.')return true; 181 | return false; 182 | } 183 | } 184 | } 185 | } 186 | return false; 187 | } 188 | 189 | bool dfs(int x, int y) 190 | { 191 | for (int i(0); i<4; ++i){ 192 | bool flag = false; 193 | int now_x = x + dir[i][0]; 194 | int now_y = y + dir[i][1]; 195 | if (law_G(now_x,now_y)){ 196 | for (int j(0); j>red_num>>b_x>>b_y){ 227 | if (red_num == 0 && b_x == 0 && b_y == 0)break; 228 | char temp; 229 | memset(map,'.',sizeof(map)); 230 | cnt = 0; 231 | int x, y; 232 | while(red_num--){ 233 | cin>>temp>>x>>y; 234 | switch(temp){ 235 | case 'G':{ 236 | map[x][y] = 'G'; 237 | break; 238 | } 239 | case 'C':{ 240 | map[x][y] = 'C'; 241 | break; 242 | } 243 | case 'H':{ 244 | map[x][y] = 'H'; 245 | break; 246 | } 247 | case 'R':{ 248 | map[x][y] = 'R'; 249 | break; 250 | } 251 | } 252 | note[cnt][0] = x; 253 | note[cnt++][1] = y; 254 | } 255 | if (dfs(b_x,b_y)){ 256 | cout<<"YES"< 2 | 3 | void let() { 4 | if(true){} 5 | if(1){} 6 | } 7 | 8 | int main() { 9 | int x = 3; 10 | if(int a = x){ 11 | int b = 1; 12 | } else if(true) { 13 | ; 14 | } else{ 15 | int c = 2; 16 | } 17 | if(x+1+2){ 18 | ; 19 | } 20 | if(true){ 21 | ; 22 | } 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /test/_init.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | void init_nop() {} 5 | /* 6 | void init_class() { 7 | string s; 8 | s = string(); 9 | s = string("xx"); 10 | std::string empty = string(); 11 | string x = "xxx"; 12 | std::string y = std::string("yyy"); 13 | y = string(); 14 | y = string("xxx"); 15 | string z = string(); 16 | z = (string)("xxx"); 17 | } 18 | */ 19 | 20 | void init_array() { 21 | bool b(2); 22 | std::string c("y"), c1, c2[] = {}, c3(c); 23 | int a[] = {1,2,}; 24 | std::string d = "yy"; 25 | string e = c; 26 | std::string f; 27 | } 28 | 29 | /* 30 | //static 31 | void init_static(int m) { 32 | int n = 2; 33 | { 34 | static int s; 35 | printf("%d\n", ++s); 36 | } 37 | } 38 | */ 39 | 40 | int main() 41 | { 42 | struct POINT{ 43 | int x, y, z; 44 | }pxx; 45 | // POINT po = pxx; 46 | // printf("%d,%d,%d\n", po.x, po.y, po.z); 47 | 48 | // init_static(1); 49 | // init_static(-10); 50 | 51 | 52 | return 0; 53 | } 54 | -------------------------------------------------------------------------------- /test/_innerclass.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | int m = 1; 5 | int n = m*m; 6 | struct HAHA{ 7 | int x; 8 | }; 9 | 10 | { 11 | struct HAHA{ 12 | int y; 13 | } AA; 14 | } 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /test/_iteration.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void nullbody() { 4 | while(true){} 5 | do{}while(true); 6 | for(;;){} 7 | } 8 | 9 | int main() { 10 | LBL_WHILE: 11 | int y; 12 | while(y = 0+3) { 13 | while(y*3 >0) { 14 | break; 15 | } 16 | continue; 17 | } 18 | LBL_DO: 19 | do{ 20 | int y = 0; 21 | if(y) break; 22 | if(!y) continue; 23 | } while(false); 24 | LBL_FOR: 25 | for(int x = 1, y; y = x; x--) { 26 | for(int j = 0; j != x; j++) { 27 | continue; 28 | } 29 | break; 30 | } 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /test/_label.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void lbl_body() { 4 | BODY0: 5 | for(int x = 0;;) { 6 | BODY1: 7 | if(x == 8 | 3 && x == 4){ 9 | BODY2: 10 | x = 1; 11 | x = 2; 12 | BODY3:{} 13 | } 14 | } 15 | } 16 | 17 | class A{ 18 | public: 19 | int m; 20 | A(int _m):m(_m){ printf("c%d\n", m); } 21 | }; 22 | 23 | int main() 24 | { 25 | // void *tbl[] = { &&LBL0, &&LBL1, &&LBL2, &&LBL3, &&LBL4, &&LBL5, &&LBL6 }; 26 | /* 27 | LBL0: 28 | int next = 0; 29 | if(next == 0) goto *tbl[1]; 30 | LBL1: 31 | int x = 1; 32 | LBL2: 33 | x = x+1; 34 | printf("%d ", x); 35 | goto LBL1; 36 | LBL3: 37 | int y = 2; 38 | LBL4: 39 | y = y - 2; 40 | goto *tbl[2]; 41 | LBL5: 42 | goto *tbl[0]; 43 | LBL6: 44 | */ 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /test/_macro.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define OP (r*r*3.14) 4 | 5 | int main() 6 | { 7 | double r = 3, s; 8 | s = OP; 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /test/_map.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | return 0; 5 | } 6 | -------------------------------------------------------------------------------- /test/_memhack.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | class S1 : public string { 6 | public: 7 | void id() { 8 | puts("1"); 9 | } 10 | }; 11 | 12 | class S2 : public string { 13 | public: 14 | int xx[10]; 15 | void id() { 16 | puts("2"); 17 | } 18 | }; 19 | 20 | 21 | int main() { 22 | S1 *p = new S1[10]; 23 | 24 | p[3].assign("yyy"); 25 | printf("&p[2] = %u\n", (unsigned int)(p+2)); 26 | S2 *q = (S2*)(p+2); 27 | printf("q = %u\n", (unsigned int)(q)); 28 | while(true) 29 | q = new S2(); 30 | printf("new q = %u\n", (unsigned int)(q)); 31 | 32 | printf("sp = %d, sq = %d\n", sizeof(p[2]), sizeof(*q)); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /test/_nested.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void str() { 5 | std::string a; 6 | } 7 | 8 | 9 | void vec() { 10 | std::vector b; 11 | b = std::vector(); 12 | } 13 | 14 | int main() { 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /test/_new.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | using namespace std; 5 | 6 | class A{ 7 | public: 8 | int _x; 9 | char *buf; 10 | A(int x=0):_x(x), buf(new char[10240]){ 11 | buf[0] = 'a'; buf[273] = 'b'; buf[1734] = 'c'; buf[9317] = 'd'; 12 | } 13 | ~A(){ delete[] buf; puts("d");} 14 | void S(){printf("x%d\n", _x);} 15 | }; 16 | 17 | class B{ 18 | public: 19 | int _x[10240]; 20 | }; 21 | 22 | int main() 23 | { 24 | int x; 25 | string y; 26 | A z, *pz = &z; 27 | void *vals[10] = {}; 28 | for(int i = 0; ; i++){ 29 | B* pb = new B; 30 | 31 | //new (&y) string("yy"); 32 | //new (&x) int(i); 33 | //new (pz) A(i); 34 | } 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /test/_ns.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | string a; 6 | string b = a; 7 | string c(""); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /test/_operator.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int main() { 5 | int x; 6 | if(cin >> x) {} 7 | if(cin){} 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /test/_paren.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void paren_cast() { 4 | int *p; 5 | int a = ( (p) && (*p) ) && long((p+1)); 6 | } 7 | 8 | int main() { 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /test/_pointer.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void func(int x) {} 4 | 5 | int main() { 6 | void (*fp)(int) = func; 7 | void (*&fpr)(int) = fp; 8 | //(*fp)(0); 9 | //(*fpr)(0); 10 | 11 | int a = 2, b = 3; 12 | int *p = &a; 13 | 14 | printf("b = %d\n", *(p+2)); 15 | 16 | return 0; 17 | } 18 | -------------------------------------------------------------------------------- /test/_ptr.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | string::size_type (string::* pmf)()const = &string::length; 8 | string tmp("heloo"); 9 | printf("%d", (tmp.*pmf)()); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /test/_ref.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | using namespace std; 4 | /* 5 | void func(int *&x) { 6 | printf("%d\n", *x); 7 | 8 | } 9 | 10 | */ 11 | void ref_in_expr(int *x) { 12 | int *&p = x; 13 | *p = (*x+*(p+1)) - p[-1]; 14 | int **pp = &p; 15 | for(;;) { 16 | int rf = 0; 17 | } 18 | class CC{ 19 | void func() { int rcx = 1; } 20 | }; 21 | } 22 | 23 | int main() { 24 | //array type reference 25 | //func(x); 26 | //false posi 27 | /* 28 | int a[3][2][1] = { {1}, {2}, {3} }; 29 | 30 | int (&ra)[3][2][1] = a; 31 | 32 | int (*pa)[3][2][1] = &a; 33 | 34 | printf("%d %d\n", ra[1][0][0], (*pa)[1][0][0]); 35 | */ 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /test/_struct.cpp: -------------------------------------------------------------------------------- 1 | struct option { 2 | char a[32]; 3 | int b; 4 | unsigned c; 5 | char d; 6 | }; 7 | 8 | int main() { 9 | option haha = {"aa", 1, 2, '3'}; // error 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /test/_switch.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | /* 3 | void simple() { 4 | int x = 1; 5 | switch(int y = x) { 6 | case 1: 7 | break; 8 | case 2: 9 | { 10 | break; 11 | } 12 | default: 13 | break; 14 | } 15 | } 16 | 17 | void assign_cond() { 18 | int x = 1, y = 2; 19 | switch(x = y) { 20 | printf("%d\n", x); 21 | case 1: ; 22 | } 23 | 24 | switch(x) { 25 | default: 26 | x = 1; 27 | case 1: 28 | y = 2; 29 | switch(y) { 30 | case 2: 31 | break; 32 | } 33 | y++; 34 | } 35 | 36 | } 37 | */ 38 | 39 | int g = 1; 40 | int main() 41 | { 42 | /* 43 | int a = 0; 44 | switch(g) { 45 | case '1' : 46 | { 47 | int b = 1; 48 | break; 49 | } 50 | case '2': 51 | { 52 | break; 53 | } 54 | case '3': 55 | { 56 | break; 57 | } 58 | } 59 | */ 60 | /* 61 | assign_cond(); 62 | int x = 1, y = x*2; 63 | int next = 0; 64 | 65 | switch(int next = x*y) { 66 | for(;;){} 67 | case 0: 68 | LBL_IN_CASE: 69 | next = 2; 70 | LBL_BEFORE_CASE: 71 | case 2 ... 3: 72 | break; 73 | if(next == 3) { 74 | for(;;){ 75 | case 6: 76 | break; 77 | } 78 | } 79 | case 4: 80 | y = y - 2; 81 | next = 3; 82 | break; 83 | case 5: 84 | ; 85 | default: 86 | goto LBL_BEFORE_CASE; 87 | LBL_BEFORE_BREAK: 88 | break; 89 | } 90 | 91 | */ 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /test/_test.cpp: -------------------------------------------------------------------------------- 1 | #include "_test.h" 2 | #include 3 | using namespace std; 4 | 5 | int recursive(int x) { 6 | ____lbl____2: 7 | goto ____lbl____2; 8 | return x > 0 ? recursive(x-1) + x : x; 9 | } 10 | 11 | int main() { 12 | int a = 0; 13 | /* 14 | while(a < 3) { 15 | cout << "a"; 16 | a++; 17 | } 18 | 19 | do { 20 | cout << "b" ; 21 | } while(++a < 6); 22 | */ 23 | void *cmd[] = { &&____lbl____3 }; 24 | ____lbl____3: 25 | cout << "haha"; 26 | for(int i = 0; i < 10; ++i) { 27 | for(int j = 0; j < 2; j++){ 28 | cout << i << "," << j << "\n"; 29 | goto *cmd[0]; 30 | } 31 | for(;; i++); 32 | for( ;i<0;) recursive(i); 33 | for(int k = 0; k < 3; ++k) 34 | cout << i << "," << k << "xx\n"; 35 | } 36 | MyClass c; 37 | c.out(10); 38 | 39 | return 0; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /test/_test.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | template 4 | class MyClass { 5 | public: 6 | void out(T x) { 7 | int a = 0; 8 | while(a++ < 3) { 9 | std::cout << x << a << std::endl; 10 | for(int i = 0; i < 10 ;i++){ 11 | } 12 | } 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /test/_tpl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | template 5 | class Class { 6 | T func(); 7 | void func2(T t){ while(true){}; int u; } 8 | }; 9 | 10 | template 11 | T Class::func() { 12 | for(int u;;) { 13 | int t = u; 14 | } 15 | } 16 | /* 17 | template 18 | void funttt(T a) { 19 | T b = a; 20 | T c(a); 21 | } 22 | */ 23 | 24 | int main() { 25 | return 0; 26 | } 27 | -------------------------------------------------------------------------------- /test/_using.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "_using1.h" //ns1::a 3 | #include "_using2.h" //ns2::a 4 | 5 | int main() { 6 | 7 | int x = ns1::a, y = ns2::a; 8 | namespace lns1{ 9 | int a = 1; 10 | } 11 | namespace lns2{ 12 | int a = 2; 13 | } 14 | 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /test/_using1.h: -------------------------------------------------------------------------------- 1 | namespace ns1 { 2 | int a = 10; 3 | }; 4 | -------------------------------------------------------------------------------- /test/_using2.h: -------------------------------------------------------------------------------- 1 | namespace ns2 { 2 | int a = 20; 3 | }; 4 | -------------------------------------------------------------------------------- /test/_vardecl.cpp: -------------------------------------------------------------------------------- 1 | int func(int a1, int a2 = 10) { 2 | return func(a1, 2); 3 | }; 4 | 5 | int main() { 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /test/_while.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void in_switch() { 4 | int x; 5 | while(2){ 6 | switch(int x = 0) { 7 | default: 8 | continue; 9 | while(true){ 10 | case 1: 11 | break; 12 | case 2: 13 | continue; 14 | } 15 | } 16 | } 17 | } 18 | 19 | int main() { 20 | int n = 12; 21 | while(int a = n + 12) { 22 | int b = n--; 23 | while(b < 11) { 24 | if(++b > 20) continue; 25 | if(b > 15) break; 26 | } 27 | printf("%d %d\n", a, b); 28 | } 29 | 30 | while(n == 12){ 31 | n++; 32 | } 33 | int y = n+2; 34 | y *= 2; 35 | return 0; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /test/a0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolf5x/cppobfuscator/d297de91e09968204b25c3af6b100fd884f2278c/test/a0.png -------------------------------------------------------------------------------- /test/a1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wolf5x/cppobfuscator/d297de91e09968204b25c3af6b100fd884f2278c/test/a1.png --------------------------------------------------------------------------------