From 51ab414c1c857fd5068e4d6f37430cbe82cfa227 Mon Sep 17 00:00:00 2001 From: Asher Baker Date: Thu, 19 Jul 2018 17:33:19 +0100 Subject: [PATCH] Add Windows support to test tool --- appveyor.yml | 3 ++ breakpad.bat | 20 +++++----- buildbot/PackageScript | 5 +-- test/AMBuilder | 22 ++++++----- test/test.cpp | 86 ++++++++++++++++++++++++++++-------------- 5 files changed, 86 insertions(+), 50 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 8b7200e..47bb01a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,6 +9,7 @@ install: - cd ambuild - C:\python27\python.exe setup.py install - cd %APPVEYOR_BUILD_FOLDER% + - '"%VS140COMNTOOLS%\vsvars32.bat"' - breakpad.bat build_script: - '"%VS140COMNTOOLS%\vsvars32.bat"' @@ -18,3 +19,5 @@ build_script: - C:\python27\python.exe build.py on_success: - C:\python27\python.exe ..\upload.py +#on_finish: +# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) diff --git a/breakpad.bat b/breakpad.bat index 0f71096..87b7026 100644 --- a/breakpad.bat +++ b/breakpad.bat @@ -1,3 +1,5 @@ +@echo on + IF EXIST breakpad\NUL GOTO HASBREAKPAD mkdir breakpad :HASBREAKPAD @@ -18,15 +20,15 @@ IF EXIST gyp\NUL GOTO HASGYP git clone --depth=1 --branch=master https://chromium.googlesource.com/external/gyp.git gyp :HASGYP -IF EXIST build\NUL GOTO HASBUILD -mkdir build -:HASBUILD -cd build +powershell -Command "& {(Get-Content src\src\build\common.gypi).replace('''WarnAsError'': ''true'',', '''WarnAsError'': ''false'',') | Set-Content src\src\build\common.gypi}" -..\gyp\gyp.bat --no-circular-check ..\src\src\client\windows\handler\exception_handler.gyp -msbuild ..\src\src\client\windows\handler\exception_handler.sln /m /p:Configuration=Release +cmd /c gyp\gyp.bat --no-circular-check src\src\client\windows\handler\exception_handler.gyp +msbuild src\src\client\windows\handler\exception_handler.sln /m /p:Configuration=Release -..\gyp\gyp.bat --no-circular-check ..\src\src\client\windows\crash_generation\crash_generation.gyp -msbuild ..\src\src\client\windows\crash_generation\crash_generation.sln /m /p:Configuration=Release +cmd /c gyp\gyp.bat --no-circular-check src\src\client\windows\crash_generation\crash_generation.gyp +msbuild src\src\client\windows\crash_generation\crash_generation.sln /m /p:Configuration=Release -cd ..\.. +cmd /c gyp\gyp.bat --no-circular-check src\src\processor\processor.gyp +msbuild src\src\processor\processor.sln /m /p:Configuration=Release + +cd .. diff --git a/buildbot/PackageScript b/buildbot/PackageScript index 9df9552..b9257ec 100644 --- a/buildbot/PackageScript +++ b/buildbot/PackageScript @@ -116,10 +116,7 @@ def AddHL2Library(name, dest): debug_info = [] AddNormalLibrary('accelerator.ext', 'extensions') - - -if AMBuild.target['platform'] == 'linux': - AddExecutable('test-crash-dump-generation', 'configs') +AddExecutable('test-crash-dump-generation', 'configs') job.AddCommandGroup(bincopies) diff --git a/test/AMBuilder b/test/AMBuilder index 375cd22..0b25880 100644 --- a/test/AMBuilder +++ b/test/AMBuilder @@ -6,7 +6,7 @@ from ambuild.command import ShellCommand from ambuild.command import DirectCommand def BuildEverything(): - if AMBuild.target['platform'] not in ['linux']: + if AMBuild.target['platform'] not in ['linux', 'windows']: return compiler = SM.DefaultCompiler() @@ -16,6 +16,9 @@ def BuildEverything(): if AMBuild.target['platform'] in ['linux']: compiler['POSTLINKFLAGS'].append('-lstdc++') compiler['POSTLINKFLAGS'].append('-pthread') + elif compiler.cc.name == 'msvc': + compiler['POSTLINKFLAGS'].remove('/SUBSYSTEM:WINDOWS') + compiler['POSTLINKFLAGS'].append('/SUBSYSTEM:CONSOLE') name = 'test-crash-dump-generation' extension = AMBuild.AddJob(name) @@ -42,18 +45,19 @@ def BuildEverything(): binary.AddObjectFiles([lib]) elif AMBuild.target['platform'] in ['windows']: - libs = ['exception_handler', 'common'] - for lib in libs: - path = os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'client', 'windows', 'handler', 'Release', 'lib', lib + '.lib') + libs = [ + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'client', 'windows', 'handler', 'Release', 'lib', 'common.lib'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'client', 'windows', 'handler', 'Release', 'lib', 'exception_handler.lib'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'client', 'windows', 'crash_generation', 'Release', 'lib', 'crash_generation_client.lib'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'processor', 'Release', 'lib', 'libdisasm.lib'), + os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'processor', 'Release', 'lib', 'processor.lib'), + ] + + for path in libs: if os.path.isfile(path): binary.RelinkIfNewer(path) binary['POSTLINKFLAGS'].extend([path]) - path = os.path.join(AMBuild.sourceFolder, 'breakpad', 'src', 'src', 'client', 'windows', 'crash_generation', 'Release', 'lib', 'crash_generation_client.lib') - if os.path.isfile(path): - binary.RelinkIfNewer(path) - binary['POSTLINKFLAGS'].extend([path]) - SM.ExtractDebugInfo(extension, binary) binary.SendToJob() diff --git a/test/test.cpp b/test/test.cpp index 7c37f88..828dd3d 100644 --- a/test/test.cpp +++ b/test/test.cpp @@ -1,7 +1,30 @@ +#if defined _LINUX #include "client/linux/handler/exception_handler.h" #include "common/linux/linux_libc_support.h" #include "third_party/lss/linux_syscall_support.h" +#include +#include +#include + +#define my_jmp_buf sigjmp_buf +#define my_setjmp(x) sigsetjmp(x, 0) +#define my_longjmp siglongjmp + +using google_breakpad::MinidumpDescriptor; + +#elif defined _WINDOWS +#define _STDINT // ~.~ +#include "client/windows/handler/exception_handler.h" + +#define my_jmp_buf jmp_buf +#define my_setjmp(x) setjmp(x) +#define my_longjmp longjmp + +#else +#error Bad platform. +#endif + #include #include #include @@ -9,14 +32,10 @@ #include #include -#include -#include -#include -#include - #include -using google_breakpad::MinidumpDescriptor; +#include + using google_breakpad::ExceptionHandler; using google_breakpad::Minidump; @@ -28,9 +47,10 @@ using google_breakpad::StackFrame; using google_breakpad::PathnameStripper; using google_breakpad::CodeModule; -sigjmp_buf envbuf; +my_jmp_buf envbuf; char path[1024]; +#if defined _LINUX static bool dumpCallback(const MinidumpDescriptor &descriptor, void *context, bool succeeded) { if (succeeded) { @@ -43,10 +63,28 @@ static bool dumpCallback(const MinidumpDescriptor &descriptor, void *context, bo sys_write(STDOUT_FILENO, "\n", 1); my_strlcpy(path, descriptor.path(), sizeof(path)); - siglongjmp(envbuf, 1); + my_longjmp(envbuf, 1); return succeeded; } +#elif defined _WINDOWS +static bool dumpCallback(const wchar_t *dump_path, const wchar_t *minidump_id, void *context, EXCEPTION_POINTERS *exinfo, MDRawAssertionInfo *assertion, bool succeeded) +{ + if (succeeded) { + printf("Wrote minidump to: %ls\\%ls.dmp\n", dump_path, minidump_id); + } else { + printf("Failed to write minidump to: %ls\\%ls.dmp\n", dump_path, minidump_id); + } + + // TODO: setjmp/longjmp doesn't play nicely with SEH on Windows, so we never get back. + // But the exception handler is called and writes the dump, so the user can just invoke us again. + + // snprintf(path, sizeof(path), "%ls\\%ls.dmp", dump_path, minidump_id); + // my_longjmp(envbuf, 1); + + return succeeded; +} +#endif int main(int argc, char *argv[]) { @@ -54,12 +92,16 @@ int main(int argc, char *argv[]) if (argc <= 1) { generateCrash = true; - if (sigsetjmp(envbuf, 0) == 0) { + if (my_setjmp(envbuf) == 0) { +#if defined _LINUX MinidumpDescriptor descriptor("."); ExceptionHandler *handler = new ExceptionHandler(descriptor, NULL, dumpCallback, NULL, true, -1); +#elif defined _WINDOWS + ExceptionHandler *handler = new ExceptionHandler(L".", NULL, dumpCallback, NULL, ExceptionHandler::HANDLER_ALL); +#endif - // Test shit here. - __builtin_trap(); + volatile int *ptr = (volatile int *)(0xdeadbeef); + *ptr = 0; delete handler; return 0; @@ -70,19 +112,9 @@ int main(int argc, char *argv[]) argc = 2; } -#define ONELINE - -#ifdef ONELINE -# define CRPRE "|" -# define CRPOST "" -#else -# define CRPRE "" -# define CRPOST "\n" -#endif - for (int i = 1; i < argc; ++i) { if (!generateCrash) { - my_strlcpy(path, argv[i], sizeof(path)); + strncpy(path, argv[i], sizeof(path)); } MinidumpProcessor minidumpProcessor(nullptr, nullptr); @@ -115,7 +147,7 @@ int main(int argc, char *argv[]) frameCount = 10; } - printf("1|%d|%s|%x|%d" CRPOST, processState.crashed(), processState.crash_reason().c_str(), (intptr_t)processState.crash_address(), requestingThread); + printf("1|%d|%s|%x|%d", processState.crashed(), processState.crash_reason().c_str(), (intptr_t)processState.crash_address(), requestingThread); std::map moduleMap; @@ -126,7 +158,7 @@ int main(int argc, char *argv[]) auto debugFile = PathnameStripper::File(module->debug_file()); auto debugIdentifier = module->debug_identifier(); - printf(CRPRE "M|%s|%s" CRPOST, debugFile.c_str(), debugIdentifier.c_str()); + printf("|M|%s|%s", debugFile.c_str(), debugIdentifier.c_str()); } for (int frameIndex = 0; frameIndex < frameCount; ++frameIndex) { @@ -135,15 +167,13 @@ int main(int argc, char *argv[]) auto moduleIndex = moduleMap[frame->module]; auto moduleOffset = frame->ReturnAddress() - frame->module->base_address(); - printf(CRPRE "F|%d|%x" CRPOST, moduleIndex, (intptr_t)moduleOffset); + printf("|F|%d|%x", moduleIndex, (intptr_t)moduleOffset); } else { - printf(CRPRE "F|%d|%x" CRPOST, -1, (intptr_t)frame->ReturnAddress()); + printf("|F|%d|%x", -1, (intptr_t)frame->ReturnAddress()); } } -#ifdef ONELINE printf("\n"); -#endif } if (generateCrash) {