FuzzApp.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #pragma warning(disable:4996)
  2. #include "FuzzApp.h"
  3. #include <iostream>
  4. #include "BeefySysLib/util/String.h"
  5. #include "BeefySysLib/util/FileEnumerator.h"
  6. #include "BeefySysLib/util/WorkThread.h"
  7. #include "BeefySysLib/platform/PlatformHelper.h"
  8. #include "Compiler/BfSystem.h"
  9. #ifdef BF_PLATFORM_WINDOWS
  10. #include <direct.h>
  11. #endif
  12. BF_IMPORT void BF_CALLTYPE Targets_Create();
  13. BF_IMPORT void BF_CALLTYPE Targets_Delete();
  14. BF_IMPORT void BF_CALLTYPE BfSystem_ReportMemory(void* bfSystem);
  15. BF_EXPORT void BF_CALLTYPE BfCompiler_ProgramDone();
  16. BF_IMPORT void BF_CALLTYPE Debugger_FullReportMemory();
  17. //////////////////////////////////////////////////////////////////////////
  18. BF_IMPORT void BF_CALLTYPE BfCompiler_Delete(void* bfCompiler);
  19. BF_EXPORT void BF_CALLTYPE BfCompiler_SetOptions(void* bfCompiler, void* hotProject, int hotIdx,
  20. const char* targetTriple, const char* targetCPU, int toolsetType, int simdSetting, int allocStackCount, int maxWorkerThreads,
  21. Beefy::BfCompilerOptionFlags optionFlags, const char* mallocLinkName, const char* freeLinkName);
  22. BF_IMPORT void BF_CALLTYPE BfCompiler_ClearBuildCache(void* bfCompiler);
  23. BF_IMPORT bool BF_CALLTYPE BfCompiler_Compile(void* bfCompiler, void* bfPassInstance, const char* outputPath);
  24. BF_IMPORT float BF_CALLTYPE BfCompiler_GetCompletionPercentage(void* bfCompiler);
  25. BF_IMPORT const char* BF_CALLTYPE BfCompiler_GetUsedOutputFileNames(void* bfCompiler, void* bfProject, bool flushQueuedHotFiles, bool* hadOutputChanges);
  26. BF_IMPORT void* BF_CALLTYPE BfSystem_CreateParser(void* bfSystem, void* bfProject);
  27. BF_IMPORT void BF_CALLTYPE BfParser_SetSource(void* bfParser, const char* data, int length, const char* fileName);
  28. BF_IMPORT void BF_CALLTYPE BfParser_SetCharIdData(void* bfParser, uint8* data, int length);
  29. BF_IMPORT bool BF_CALLTYPE BfParser_Parse(void* bfParser, void* bfPassInstance, bool compatMode);
  30. BF_IMPORT bool BF_CALLTYPE BfParser_Reduce(void* bfParser, void* bfPassInstance);
  31. BF_IMPORT bool BF_CALLTYPE BfParser_BuildDefs(void* bfParser, void* bfPassInstance, void* resolvePassData, bool fullRefresh);
  32. //////////////////////////////////////////////////////////////////////////
  33. BF_IMPORT void* BF_CALLTYPE BfSystem_Create();
  34. BF_EXPORT void BF_CALLTYPE BfSystem_Lock(void* bfSystem, int priority);
  35. BF_EXPORT void BF_CALLTYPE BfSystem_Unlock(void* bfSystem);
  36. BF_IMPORT void BF_CALLTYPE BfSystem_ReportMemory(void* bfSystem);
  37. BF_IMPORT void BF_CALLTYPE BfSystem_Delete(void* bfSystem);
  38. BF_IMPORT void* BF_CALLTYPE BfSystem_CreatePassInstance(void* bfSystem);
  39. BF_IMPORT void* BF_CALLTYPE BfSystem_CreateCompiler(void* bfSystem, bool isResolveOnly);
  40. BF_IMPORT void* BF_CALLTYPE BfSystem_CreateProject(void* bfSystem, const char* projectName, const char* projectDir);
  41. BF_IMPORT void BF_CALLTYPE BfParser_Delete(void* bfParser);
  42. BF_IMPORT void BF_CALLTYPE BfSystem_AddTypeOptions(void* bfSystem, const char* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 arrayBoundsCheck,
  43. int32 initLocalVariables, int32 emitDynamicCastCheck, int32 emitObjectAccessCheck, int32 allocStackTraceDepth);
  44. //////////////////////////////////////////////////////////////////////////
  45. BF_IMPORT void BF_CALLTYPE BfProject_SetDisabled(void* bfProject, bool disabled);
  46. BF_IMPORT void BF_CALLTYPE BfProject_SetOptions(void* bfProject, int targetType, const char* startupObject, const char* preprocessorMacros,
  47. int optLevel, int ltoType, int relocType, int picLevel, int32 flags);
  48. BF_IMPORT void BF_CALLTYPE BfProject_ClearDependencies(void* bfProject);
  49. BF_IMPORT void BF_CALLTYPE BfProject_AddDependency(void* bfProject, void* depProject);
  50. //////////////////////////////////////////////////////////////////////////
  51. BF_IMPORT const char* BF_CALLTYPE BfPassInstance_PopOutString(void* bfPassInstance);
  52. BF_IMPORT void BF_CALLTYPE BfPassInstance_Delete(void* bfPassInstance);
  53. //////////////////////////////////////////////////////////////////////////
  54. BF_IMPORT const char* BF_CALLTYPE VSSupport_Find();
  55. //////////////////////////////////////////////////////////////////////////
  56. USING_NS_BF;
  57. FuzzApp* Beefy::gApp = NULL;
  58. FuzzApp::FuzzApp()
  59. {
  60. Targets_Create();
  61. mTargetType = BfTargetType_BeefConsoleApplication;
  62. mSystem = NULL;
  63. mCompiler = NULL;
  64. mProject = NULL;
  65. mCELibProject = NULL;
  66. mIsCERun = false;
  67. mStartupObject = "Program";
  68. #ifdef BF_PLATFORM_WINDOWS
  69. mOptLevel = BfOptLevel_OgPlus;
  70. mToolset = BfToolsetType_Microsoft;
  71. #else
  72. mOptLevel = BfOptLevel_O0;
  73. mToolset = BfToolsetType_GNU;
  74. #endif
  75. #ifdef BF_PLATFORM_WINDOWS
  76. mTargetTriple = "x86_64-pc-windows-msvc";
  77. #elif defined BF_PLATFORM_MACOS
  78. mTargetTriple = "x86_64-apple-macosx10.8.0";
  79. #else
  80. mTargetTriple = "x86_64-unknown-linux-gnu";
  81. #endif
  82. }
  83. FuzzApp::~FuzzApp()
  84. {
  85. Targets_Delete();
  86. }
  87. bool FuzzApp::Init()
  88. {
  89. char* cwdPtr = getcwd(NULL, 0);
  90. mWorkingDir = cwdPtr;
  91. free(cwdPtr);
  92. if (mTargetPath.IsEmpty())
  93. return false;
  94. return true;
  95. }
  96. bool FuzzApp::QueueFile(const char* data, size_t len)
  97. {
  98. bool worked = true;
  99. void* bfParser = BfSystem_CreateParser(mSystem, (mCELibProject != NULL) ? mCELibProject : mProject);
  100. BfParser_SetSource(bfParser, data, len, "Fuzz.bf");
  101. //bfParser.SetCharIdData(charIdData);
  102. worked &= BfParser_Parse(bfParser, mPassInstance, false);
  103. worked &= BfParser_Reduce(bfParser, mPassInstance);
  104. worked &= BfParser_BuildDefs(bfParser, mPassInstance, NULL, false);
  105. return worked;
  106. }
  107. bool FuzzApp::QueuePath(const StringImpl& path)
  108. {
  109. if (DirectoryExists(path))
  110. {
  111. for (auto& fileEntry : FileEnumerator(path, FileEnumerator::Flags_Files))
  112. {
  113. String filePath = fileEntry.GetFilePath();
  114. String fileName;
  115. fileName = GetFileName(filePath);
  116. String ext;
  117. ext = GetFileExtension(filePath);
  118. if ((ext.Equals(".bf", StringImpl::CompareKind_OrdinalIgnoreCase)) ||
  119. (ext.Equals(".cs", StringImpl::CompareKind_OrdinalIgnoreCase)))
  120. {
  121. int len;
  122. const char* data = LoadTextData(filePath, &len);
  123. if (data != NULL)
  124. {
  125. bool success = QueueFile(data, len);
  126. delete[] data;
  127. if (!success)
  128. return false;
  129. }
  130. }
  131. }
  132. for (auto& fileEntry : FileEnumerator(path, FileEnumerator::Flags_Directories))
  133. {
  134. String childPath = fileEntry.GetFilePath();
  135. String dirName;
  136. dirName = GetFileName(childPath);
  137. if (dirName == "build")
  138. continue;
  139. if (!QueuePath(childPath))
  140. return false;
  141. }
  142. return true;
  143. }
  144. return false;
  145. }
  146. bool FuzzApp::CopyFile(const StringImpl& srcPath, const StringImpl& destPath)
  147. {
  148. BfpFileResult result = BfpFileResult_Ok;
  149. for (int i = 0; i < 20; i++)
  150. {
  151. BfpFile_Copy(srcPath.c_str(), destPath.c_str(), BfpFileCopyKind_Always, &result);
  152. if (result == BfpFileResult_Ok)
  153. return true;
  154. BfpThread_Sleep(100);
  155. }
  156. return false;
  157. }
  158. void FuzzApp::PrepareCompiler()
  159. {
  160. mSystem = BfSystem_Create();
  161. mCompiler = BfSystem_CreateCompiler(mSystem, false);
  162. String projectName = GetFileName(mTargetPath);
  163. int dotPos = (int)projectName.IndexOf('.');
  164. if (dotPos != -1)
  165. projectName.RemoveToEnd(dotPos);
  166. if (projectName.IsEmpty())
  167. projectName.Append("BeefProject");
  168. mProject = BfSystem_CreateProject(mSystem, projectName.c_str(), GetFileDir(mTargetPath).c_str());
  169. if (mIsCERun)
  170. {
  171. mCELibProject = BfSystem_CreateProject(mSystem, "BeefLib", GetFileDir(mTargetPath).c_str());
  172. BfProject_SetOptions(mCELibProject, BfTargetType_BeefLib, "", mDefines.c_str(), mOptLevel, 0, 0, 0, BfProjectFlags_None);
  173. }
  174. String defines = mDefines;
  175. if (!defines.IsEmpty())
  176. defines.Append("\n");
  177. defines.Append("BF_64_BIT");
  178. defines.Append("\nBF_LITTLE_ENDIAN");
  179. defines.Append("\n");
  180. defines.Append(BF_PLATFORM_NAME);
  181. int ltoType = 0;
  182. BfProject_SetOptions(mProject, mTargetType, mStartupObject.c_str(), defines.c_str(), BfOptLevel_O0, ltoType, 0, 0, BfProjectFlags_None);
  183. if (mCELibProject != NULL)
  184. BfProject_AddDependency(mProject, mCELibProject);
  185. mPassInstance = BfSystem_CreatePassInstance(mSystem);
  186. Beefy::String exePath;
  187. BfpGetStrHelper(exePath, [](char* outStr, int* inOutStrSize, BfpResult* result)
  188. {
  189. BfpSystem_GetExecutablePath(outStr, inOutStrSize, (BfpSystemResult*)result);
  190. });
  191. mBuildDir = GetFileDir(exePath) + "/build";
  192. RecursiveCreateDirectory(mBuildDir + "/" + projectName);
  193. if (mIsCERun)
  194. RecursiveCreateDirectory(mBuildDir + "/BeefLib");
  195. BfCompilerOptionFlags optionFlags = (BfCompilerOptionFlags)(BfCompilerOptionFlag_EmitDebugInfo | BfCompilerOptionFlag_EmitLineInfo | BfCompilerOptionFlag_GenerateOBJ | BfCompilerOptionFlag_OmitDebugHelpers);
  196. //int maxWorkerThreads = BfpSystem_GetNumLogicalCPUs(NULL);
  197. //if (maxWorkerThreads <= 1)
  198. // maxWorkerThreads = 6;
  199. BfCompiler_SetOptions(mCompiler, NULL, 0, mTargetTriple.c_str(), "", mToolset, BfSIMDSetting_SSE2, 1, 1, optionFlags, "malloc", "free");
  200. }
  201. bool FuzzApp::Compile()
  202. {
  203. BfCompiler_ClearBuildCache(mCompiler);
  204. if (!BfCompiler_Compile(mCompiler, mPassInstance, mBuildDir.c_str()))
  205. return false;
  206. if (!mCEDest.IsEmpty())
  207. {
  208. String ext;
  209. String srcResult = mBuildDir + "/BeefProject/BeefProject";
  210. srcResult += BF_OBJ_EXT;
  211. if (!CopyFile(srcResult, mCEDest))
  212. return false;
  213. }
  214. while (true)
  215. {
  216. const char* msg = BfPassInstance_PopOutString(mPassInstance);
  217. if (msg == NULL)
  218. break;
  219. if ((strncmp(msg, ":error ", 7) == 0) ||
  220. (strncmp(msg, "ERROR(", 6) == 0) ||
  221. (strncmp(msg, "ERROR:", 6) == 0))
  222. {
  223. return false;
  224. }
  225. }
  226. return true;
  227. }
  228. void FuzzApp::ReleaseCompiler()
  229. {
  230. BfPassInstance_Delete(mPassInstance);
  231. BfCompiler_Delete(mCompiler);
  232. BfSystem_Delete(mSystem);
  233. }