├── .editorconfig ├── .gitattributes ├── .gitignore ├── .gitmodules ├── COPYING.LIB ├── README.md ├── appveyor.yml ├── build.cmd ├── dbghelp_x64 ├── dbghelpms.dll ├── dbghelpms6.dll ├── srcsrv.dll ├── symsrv.dll └── symsrv.yes ├── dbghelp_x86 ├── dbghelpms.dll ├── dbghelpms6.dll ├── srcsrv.dll ├── symsrv.dll └── symsrv.yes ├── installer.iss ├── keywords.txt ├── license.rtf ├── license.txt ├── osfunctions.txt ├── osmodules.txt ├── sleepy.sln ├── sleepy.vcxproj ├── sleepy.vcxproj.filters ├── src ├── appinfo.h ├── copyfiles.bat ├── crashback │ ├── .gitignore │ ├── badapp │ │ ├── badapp.cpp │ │ └── badapp.vcxproj │ ├── client │ │ ├── client.cpp │ │ ├── crashback.h │ │ └── crashback.vcxproj │ ├── crashreport │ │ ├── crashreport.cpp │ │ ├── crashreport.h │ │ ├── crashreport.rc │ │ ├── crashreport.vcxproj │ │ └── resource.h │ └── web │ │ └── crashback.php ├── gen_version.bat ├── profiler │ ├── debugger.cpp │ ├── debugger.h │ ├── processinfo.cpp │ ├── processinfo.h │ ├── profiler.cpp │ ├── profiler.h │ ├── profilerthread.cpp │ ├── profilerthread.h │ ├── symbolinfo.cpp │ ├── symbolinfo.h │ ├── threadinfo.cpp │ └── threadinfo.h ├── res │ ├── Button-Add.png │ ├── Button-Down.png │ ├── Button-Download.png │ ├── Button-ExportCSV.png │ ├── Button-Go.png │ ├── Button-Next.png │ ├── Button-Pause.png │ ├── Button-Previous.png │ ├── Button-ProfileAll.png │ ├── Button-ProfileSel.png │ ├── Button-Refresh.png │ ├── Button-Remove.png │ ├── Button-Up.png │ ├── sleepy.ico │ └── sleepy.rc ├── utils │ ├── WoW64.cpp │ ├── WoW64.h │ ├── container.h │ ├── dbginterface.cpp │ ├── dbginterface.h │ ├── except.h │ ├── mythread.cpp │ ├── mythread.h │ ├── osutils.cpp │ ├── osutils.h │ ├── sortlist.cpp │ ├── sortlist.h │ ├── stringutils.cpp │ └── stringutils.h └── wxProfilerGUI │ ├── CallstackView.cpp │ ├── CallstackView.h │ ├── aboutdlg.cpp │ ├── aboutdlg.h │ ├── capturewin.cpp │ ├── capturewin.h │ ├── contextmenu.cpp │ ├── contextmenu.h │ ├── database.cpp │ ├── database.h │ ├── latesymbolinfo.cpp │ ├── latesymbolinfo.h │ ├── launchdlg.cpp │ ├── launchdlg.h │ ├── logview.cpp │ ├── logview.h │ ├── mainwin.cpp │ ├── mainwin.h │ ├── optionsdlg.cpp │ ├── optionsdlg.h │ ├── processlist.cpp │ ├── processlist.h │ ├── proclist.cpp │ ├── proclist.h │ ├── profilergui.cpp │ ├── profilergui.h │ ├── sourceview.cpp │ ├── sourceview.h │ ├── threadlist.cpp │ ├── threadlist.h │ ├── threadpicker.cpp │ ├── threadpicker.h │ ├── threadsview.cpp │ └── threadsview.h └── thirdparty ├── .gitignore ├── drmingw_build_mingw.cmd ├── drmingw_build_msys2.cmd ├── mingw └── .gitignore ├── ms └── dbghelp.h └── wxWidgetsSetup ├── .gitignore ├── setup.h ├── wxWidgetsSetup.vcxproj └── wxWidgetsSetup.vcxproj.filters /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.{cpp,h}] 4 | end_of_line = crlf 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | indent_style = tab 9 | indent_size = tab 10 | tab_width = 4 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * whitespace=blank-at-eol,space-before-tab,indent-with-non-tab,-tab-in-indent,blank-at-eof,cr-at-eol,tabwidth=4 2 | *.md whitespace=-blank-at-eol,space-before-tab,-indent-with-non-tab,tab-in-indent,blank-at-eof,-cr-at-eol,tabwidth=4 3 | *.yml whitespace=-blank-at-eol,space-before-tab,-indent-with-non-tab,tab-in-indent,blank-at-eof,-cr-at-eol,tabwidth=4 4 | symsrv.yes -diff 5 | *.iss whitespace=blank-at-eol,space-before-tab,-indent-with-non-tab,tab-in-indent,blank-at-eof,cr-at-eol,tabwidth=4 6 | *.vcxproj whitespace=blank-at-eol,space-before-tab,-indent-with-non-tab,tab-in-indent,blank-at-eof,cr-at-eol,tabwidth=4 7 | *.vcxproj.filters whitespace=blank-at-eol,space-before-tab,-indent-with-non-tab,tab-in-indent,blank-at-eof,cr-at-eol,tabwidth=4 8 | 9 | /COPYING.LIB whitespace=-blank-at-eol 10 | /license.rtf whitespace=-blank-at-eol 11 | /license.txt whitespace=-blank-at-eol,-indent-with-non-tab 12 | /thirdparty/ms/dbghelp.h whitespace=-blank-at-eol 13 | /thirdparty/wxWidgetsSetup/setup.h whitespace=-indent-with-non-tab,-blank-at-eof 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /obj/ 2 | /.vs/ 3 | /setup.exe 4 | 5 | /src/version.h 6 | 7 | *.VC.db 8 | *.VC.opendb 9 | *.ipch 10 | *.opensdf 11 | *.sdf 12 | *.suo 13 | *.user 14 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "thirdparty/wine"] 2 | path = thirdparty/wine 3 | url = https://github.com/VerySleepy/wine 4 | branch = sleepy 5 | [submodule "thirdparty/drmingw"] 6 | path = thirdparty/drmingw 7 | url = https://github.com/jrfonseca/drmingw 8 | [submodule "thirdparty/wxWidgets"] 9 | path = thirdparty/wxWidgets 10 | url = https://github.com/wxWidgets/wxWidgets 11 | [submodule "tests"] 12 | path = tests 13 | url = https://github.com/VerySleepy/tests 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Very Sleepy [![Build status](https://ci.appveyor.com/api/projects/status/5gf55tjd7mc80b05/branch/master?svg=true)](https://ci.appveyor.com/project/CyberShadow/verysleepy/branch/master) 2 | ----------- 3 | 4 | This is [Very Sleepy](http://www.codersnotes.com/sleepy), a sampling CPU profiler for Windows with a wxWidgets-based GUI. 5 | 6 | ![Very Sleepy screenshot](https://dump.thecybershadow.net/12df19e403014f88f368da4c2d2482a2/1.png) 7 | 8 | ### Features 9 | 10 | * Simple user interface 11 | * Microsoft Symbol Server support 12 | * [Command-line operation](https://github.com/VerySleepy/verysleepy/wiki/Command-Line-Usage) 13 | * [MinGW support](https://github.com/VerySleepy/verysleepy/wiki/Profiling-MinGW-Programs) 14 | * [Late symbol resolution](https://github.com/VerySleepy/verysleepy/wiki/Late-Symbol-Resolution) 15 | 16 | ### Documentation 17 | 18 | Very Sleepy documentation is available on [the GitHub project wiki](https://github.com/VerySleepy/verysleepy/wiki). 19 | 20 | ### Download 21 | 22 | Official releases can be downloaded from [the project's website](http://www.codersnotes.com/sleepy), or from [the GitHub releases page](https://github.com/VerySleepy/verysleepy/releases). 23 | 24 | For the latest development version, you can download [the latest AppVeyor artifact](https://ci.appveyor.com/api/projects/CyberShadow/verysleepy/artifacts/setup.exe?branch=master). 25 | 26 | ### History 27 | 28 | ##### Version 0.92 (under development): 29 | 30 | * Do not include time while paused in sample durations 31 | * Add command-line switch `/d` to wait before starting profiler 32 | * Contributed by [aaalexandrov](https://github.com/aaalexandrov): 33 | * Add sample filtering by thread ([#86](https://github.com/VerySleepy/verysleepy/pull/86)) 34 | * Profile new threads as they are created ([#88](https://github.com/VerySleepy/verysleepy/pull/88)) 35 | 36 | ##### Version 0.91 (2021-08-19): 37 | 38 | * Rename project back to Very Sleepy (this fork repository is now the official repository) 39 | * Use [Dr. MinGW](https://github.com/jrfonseca/drmingw) to resolve MinGW symbols by default 40 | * Update Wine DbgHelp for Windows 41 | * Improve and greatly simplify build process ([#40](https://github.com/VerySleepy/verysleepy/pull/40)) 42 | * Add continuous integration via [AppVeyor](https://ci.appveyor.com/project/CyberShadow/verysleepy) 43 | * Improve Visual Studio 2015 support ([#28](https://github.com/VerySleepy/verysleepy/issues/28)) 44 | * More user interface fixes and improvements 45 | * Contributed by [Bernat Muñoz Garcia](https://github.com/shashClp): 46 | * Use Scintilla for syntax highlighting ([#16](https://github.com/VerySleepy/verysleepy/pull/16)) 47 | * Contributed by [Ashod](https://github.com/Ashod): 48 | * 64-bit fixes ([#21](https://github.com/VerySleepy/verysleepy/pull/21)) 49 | * Contributed by [k4hvd1](https://github.com/k4hvd1): 50 | * Added command-line option `/a` to profile an existing process by its process ID ([#30](https://github.com/VerySleepy/verysleepy/pull/30)) 51 | * Contributed by [Markus Gaisbauer](https://github.com/quijote): 52 | * Added "Total CPU time" column ([#37](https://github.com/VerySleepy/verysleepy/pull/37)) 53 | * Improved handling of processes with many threads ([#38](https://github.com/VerySleepy/verysleepy/pull/38)) 54 | * Contributed by [Bernhard Schelling](https://github.com/schellingb): 55 | * Added Callgrind format file export feature ([#46](https://github.com/VerySleepy/verysleepy/pull/46)) 56 | * Fixed symbols (PDB files) not being unloaded after detaching ([#57](https://github.com/VerySleepy/verysleepy/pull/57)) 57 | * Improved jumping to source lines from list views ([#58](https://github.com/VerySleepy/verysleepy/pull/58)) 58 | * Contributed by [rammerchoi](https://github.com/RammerChoi): 59 | * Added command-line switch '/mt' and '/mbt' ([#48](https://github.com/VerySleepy/verysleepy/pull/48)) 60 | * Contributed by [Graeme Kelly](https://github.com/graemekelly): 61 | * Added display of thread names on threads lists ([#60](https://github.com/VerySleepy/verysleepy/pull/60)) 62 | * Added column headers to exported CSV files ([#62](https://github.com/VerySleepy/verysleepy/pull/62)) 63 | * Contributed by [Yujiang Wang](https://github.com/AlanIWBFT): 64 | * Fixed missing buttons for very long paths ([#65](https://github.com/VerySleepy/verysleepy/pull/65)) 65 | * Updated DbgHelp to 10.0.17763.1 ([#65](https://github.com/VerySleepy/verysleepy/pull/65)) 66 | * Contributed by [djdron](https://github.com/djdron): 67 | * Improved HDPI support ([#74](https://github.com/VerySleepy/verysleepy/pull/74)) 68 | * Fixed some memory leaks ([#75](https://github.com/VerySleepy/verysleepy/pull/75)) 69 | * Updated Dr.MinGW ([#77](https://github.com/VerySleepy/verysleepy/pull/77)) 70 | 71 | ##### Version 0.90 (2014-12-23): 72 | 73 | * Redesign parts of the file format and internal database representation, to allow more exact late symbol loading, as well as a disassembler view in the future 74 | * Add an "Address" column to all function lists 75 | * For the call stack and callers view, the address specifies the address past the call instruction 76 | * Several fixes to the crash reporter 77 | * Use wxWidgets 2.9.5 78 | * Fix problems caused by dbghelp.dll hijacking 79 | * Fix handling of symbols containing whitespace characters 80 | * More user interface improvements 81 | * Contributed by [Unknown W. Brackets](https://github.com/unknownbrackets): 82 | * 64-bit fixes ([#6](https://github.com/VerySleepy/verysleepy/pull/6)) 83 | * Contributed by Michael Vance: 84 | * Add CSV export for the callstack view 85 | * UI fixes and code cleanup 86 | 87 | ##### Version 0.83 (2013-08-22): 88 | 89 | * Rename fork to "Very Sleepy CS" 90 | * Numerous user interface performance, responsiveness and usability improvements 91 | * Allow specifying additional symbol search paths 92 | * Add Back and Forward menu items and hotkeys for function list navigation 93 | * Improve overall performance 94 | * Add late symbol loading by saving a minidump during profiling 95 | * Install 32-bit version alongside 64-bit version 96 | * Contributed by [Richard Munn](https://github.com/benjymous): 97 | * Added a time limit option to the interface ([#1](https://github.com/VerySleepy/verysleepy/pull/1)) 98 | * Added function highlighting and filtering ([#2](https://github.com/VerySleepy/verysleepy/pull/2)) 99 | * Interface improvements ([#3](https://github.com/VerySleepy/verysleepy/pull/3)) 100 | 101 | ##### [First fork release](http://blog.thecybershadow.net/2013/01/11/very-sleepy-fork/) (2013-01-11): 102 | 103 | * GitHub repository created 104 | * Fix several issues with the `/r` command-line option 105 | * Various UI improvements 106 | * Don't completely abort due to one failed `GetThreadContext` call (fixes "`Error: ProfilerExcep: GetThreadContext failed.`" errors by ignoring the occasional seemingly-harmless error condition) 107 | 108 | ##### Older changes 109 | 110 | Changes before this repository's creation can be found on [the project's website](http://www.codersnotes.com/programs/sleepy). 111 | 112 | ### Building 113 | 114 | #### Prerequisites 115 | 116 | * Visual C++ 2010 or newer 117 | * [CMake](https://cmake.org/) (for Dr. MinGW) 118 | * [7-Zip](http://www.7-zip.org/) (for unpacking MinGW) 119 | * [InnoSetup 5](http://www.jrsoftware.org/isinfo.php) (for building an installer) 120 | 121 | #### Instructions 122 | 123 | Third party dependencies are registered using git submodules, so you will need to either clone with the `--recursive` flag, or run `git submodule update --init` after cloning. 124 | 125 | The `build.cmd` batch file will attempt to build Very Sleepy and its dependencies. 126 | 127 | Alternatively, you can build Dr. MinGW using the `thirdparty/drmingw_build_mingw.cmd` batch file, then use the Visual Studio solution file (`sleepy.sln`) to build everything else. 128 | 129 | ### Contributing 130 | 131 | If you'd like to contribute a patch, please [open a pull request](https://github.com/VerySleepy/verysleepy/pulls). I'll try to review and merge it as soon as my time will allow. 132 | 133 | Bug reports and feature requests are welcome as well -- please file them as [GitHub issues](https://github.com/VerySleepy/verysleepy/issues). 134 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | skip_branch_with_pr: true 2 | skip_tags: true 3 | 4 | install: 5 | - choco install -y InnoSetup 6 | - git submodule update --init --recursive 7 | 8 | build_script: 9 | - build.cmd 10 | 11 | artifacts: 12 | - path: setup.exe 13 | name: Very Sleepy installer 14 | - path: symbols.7z 15 | name: Debugging symbols 16 | 17 | test_script: 18 | - tests\tests\run_tests.bat 19 | 20 | deploy: 21 | provider: GitHub 22 | tag: appveyor 23 | release: appveyor 24 | description: 'Latest build from AppVeyor CI' 25 | auth_token: 26 | secure: qqtZWL+oz2DPdI31/TicJ9/SKk+GP18zlWMNbZ21WA49P+MnNksyKAplu0PyeYQo 27 | artifact: setup.exe, symbols.7z 28 | draft: false 29 | prerelease: true 30 | force_update: true 31 | on: 32 | branch: master 33 | -------------------------------------------------------------------------------- /build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enabledelayedexpansion 3 | 4 | rem Get options from the command line 5 | 6 | for %%a in (%*) do set %%a 7 | 8 | rem Build Dr. MinGW 9 | 10 | echo build.cmd: Building Dr. MinGW 11 | call thirdparty\drmingw_build_mingw.cmd 12 | if errorlevel 1 exit /b 1 13 | 14 | rem Set up wxWidgets ignores, so that git describe 15 | rem does not think we're building with a dirty tree 16 | 17 | if exist .git\modules\thirdparty\wxWidgets\info\exclude if not exist .git\modules\thirdparty\wxWidgets\info\exclude_sleepy ( 18 | echo build.cmd: Configuring .git\modules\thirdparty\wxWidgets\info\exclude 19 | 20 | echo /build/msw/vc_mswu/>> .git\modules\thirdparty\wxWidgets\info\exclude 21 | echo /build/msw/vc_x64_mswu/>> .git\modules\thirdparty\wxWidgets\info\exclude 22 | echo /include/wx/msw/setup.h>> .git\modules\thirdparty\wxWidgets\info\exclude 23 | echo /include/wx/setup.h>> .git\modules\thirdparty\wxWidgets\info\exclude 24 | echo /lib/vc_lib/>> .git\modules\thirdparty\wxWidgets\info\exclude 25 | echo /lib/vc_x64_lib/>> .git\modules\thirdparty\wxWidgets\info\exclude 26 | 27 | echo. > .git\modules\thirdparty\wxWidgets\info\exclude_sleepy 28 | ) 29 | 30 | rem Find MSBuild 31 | 32 | if not defined MSBUILD for %%a in (msbuild.exe) do if not [%%~$PATH:a] == [] set MSBUILD=%%~$PATH:a 33 | if not defined MSBUILD if exist "%ProgramFiles(x86)%\MSBuild\14.0\Bin\MSBuild.exe" set MSBUILD=%ProgramFiles(x86)%\MSBuild\14.0\Bin\MSBuild.exe 34 | if not defined MSBUILD if exist "%ProgramFiles(x86)%\MSBuild\12.0\Bin\MSBuild.exe" set MSBUILD=%ProgramFiles(x86)%\MSBuild\12.0\Bin\MSBuild.exe 35 | if not defined MSBUILD if exist %WinDir%\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe set MSBUILD=%WinDir%\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe 36 | if not defined MSBUILD echo build.cmd: Can't find msbuild! & exit /b 1 37 | echo build.cmd: Found msbuild at: %MSBUILD% 38 | 39 | rem Find SignTool 40 | 41 | if defined SIGN ( 42 | if not defined SIGNTOOL for %%a in (signtool.exe) do if not [%%~$PATH:a] == [] set SIGNTOOL=%%~$PATH:a 43 | if not defined SIGNTOOL if defined MSSdk if exist "!MSSdk!\Bin\signtool.exe" set SIGNTOOL=!MSSdk!\Bin\signtool.exe 44 | if not defined SIGNTOOL if exist "!ProgramFiles(x86)!\Windows Kits\10\bin\x64\signtool.exe" set "SIGNTOOL=!ProgramFiles(x86)!\Windows Kits\10\bin\x64\signtool.exe" 45 | if not defined SIGNTOOL if exist "!ProgramFiles(x86)!\Windows Kits\8.1\bin\x64\signtool.exe" set "SIGNTOOL=!ProgramFiles(x86)!\Windows Kits\8.1\bin\x64\signtool.exe" 46 | if not defined SIGNTOOL if exist "!ProgramFiles(x86)!\Windows Kits\8.1\bin\x86\signtool.exe" set "SIGNTOOL=!ProgramFiles(x86)!\Windows Kits\8.1\bin\x86\signtool.exe" 47 | if not defined SIGNTOOL if exist "!ProgramFiles(x86)!\Windows Kits\8.0\bin\x64\signtool.exe" set "SIGNTOOL=!ProgramFiles(x86)!\Windows Kits\8.0\bin\x64\signtool.exe" 48 | if not defined SIGNTOOL if exist "!ProgramFiles(x86)!\Windows Kits\8.0\bin\x64\signtool.exe" set "SIGNTOOL=!ProgramFiles(x86)!\Windows Kits\8.0\bin\x64\signtool.exe" 49 | if not defined SIGNTOOL if exist "!ProgramFiles!\Microsoft SDKs\Windows\v7.1\Bin\signtool.exe" set "SIGNTOOL=!ProgramFiles!\Microsoft SDKs\Windows\v7.1\Bin\signtool.exe" 50 | if not defined SIGNTOOL if exist "!ProgramFiles!\Microsoft SDKs\Windows\v7.0\Bin\signtool.exe" set "SIGNTOOL=!ProgramFiles!\Microsoft SDKs\Windows\v7.0\Bin\signtool.exe" 51 | if not defined SIGNTOOL if exist "!ProgramFiles!\Microsoft SDKs\Windows\v6.0A\Bin\signtool.exe" set "SIGNTOOL=!ProgramFiles!\Microsoft SDKs\Windows\v6.0A\Bin\signtool.exe" 52 | if not defined SIGNTOOL echo build.cmd: Can't find SignTool! & exit /b 1 53 | echo build.cmd: Found SignTool at: !SIGNTOOL! 54 | ) 55 | 56 | rem Use the latest working toolset with Windows XP compatibility 57 | rem (v120_xp at the time of writing). 58 | 59 | rem Note: Building dbghelpw on x64 with v140_xp fails with strange 60 | rem include errors, such as "fatal error C1083: Cannot open 61 | rem include file: 'fcntl.h': No such file or directory" 62 | 63 | rem Note: MSBuild on AppVeyor has some strange problems when 64 | rem building against the v100 toolset: 65 | rem http://help.appveyor.com/discussions/problems/6000-link-fatal-error-lnk1158-cannot-run-cvtresexe 66 | 67 | if not defined TOOLSET set TOOLSET=v120_xp 68 | 69 | rem Build Very Sleepy 70 | 71 | if not defined CONFIGURATION set CONFIGURATION=Release 72 | 73 | for %%p in (Win32 x64) do ( 74 | set PLATFORM=%%p 75 | 76 | echo build.cmd: Building !CONFIGURATION! ^| !PLATFORM! 77 | 78 | rem Build for the Wow64 configuration first. 79 | rem This configuration is only used for the Wine dbghelp implemenation 80 | rem to support debugging 32-bit programs from a 64-bit host program. 81 | 82 | "%MSBUILD%" /p:Configuration="!CONFIGURATION! - Wow64" /p:Platform=!PLATFORM! /p:PlatformToolset=!TOOLSET! sleepy.sln 83 | if errorlevel 1 exit /b 1 84 | 85 | rem Now build the non-Wow64 configuration. 86 | 87 | "%MSBUILD%" /p:Configuration=!CONFIGURATION! /p:Platform=!PLATFORM! /p:PlatformToolset=!TOOLSET! sleepy.sln 88 | if errorlevel 1 exit /b 1 89 | 90 | rem Extract app information (needed by signing). 91 | rem Do this here as version.h is generated as part of the build. 92 | 93 | for /f "tokens=1,2*" %%a in (src\appinfo.h) do if [%%a] == [#define] if [%%b] == [APPNAME] set APPNAME=%%~c 94 | for /f "tokens=1,2*" %%a in (src\appinfo.h) do if [%%a] == [#define] if [%%b] == [APPURL] set APPURL=%%~c 95 | for /f "tokens=1,2*" %%a in (src\version.h) do if [%%a] == [#define] if [%%b] == [VERSION] set VERSION=%%~c 96 | 97 | rem Sign, if signing is requested. 98 | 99 | if defined SIGN "!SIGNTOOL!" sign /n "!SIGN!" /a /d "!APPNAME! v!VERSION!" /du "!APPURL!" /t http://time.certum.pl/ "obj\!PLATFORM!\!CONFIGURATION!\sleepy.exe" 100 | if errorlevel 1 exit /b 1 101 | if defined SIGN "!SIGNTOOL!" sign /n "!SIGN!" /a /d "!APPNAME! v!VERSION! crash reporter" /du "!APPURL!" /t http://time.certum.pl/ "obj\!PLATFORM!\!CONFIGURATION!\crashreport.exe" 102 | if errorlevel 1 exit /b 1 103 | ) 104 | 105 | if not %CONFIGURATION% == Release goto :eof 106 | 107 | rem Find InnoSetup 108 | 109 | if not defined INNOSETUP for %%a in (ISCC.exe) do if not [%%~$PATH:a] == [] set INNOSETUP="%%~$PATH:a" 110 | for %%v in (5 6) do ( 111 | if not defined INNOSETUP if exist "%ProgramFiles%\Inno Setup %%~v\ISCC.exe" set INNOSETUP="%ProgramFiles%\Inno Setup %%~v\ISCC.exe" 112 | if not defined INNOSETUP if exist "%ProgramFiles(x86)%\Inno Setup %%~v\ISCC.exe" set INNOSETUP="%ProgramFiles(x86)%\Inno Setup %%~v\ISCC.exe" 113 | if not defined INNOSETUP if exist "%ProgramW6432%\Inno Setup %%~v\ISCC.exe" set INNOSETUP="%ProgramW6432%\Inno Setup %%~v\ISCC.exe" 114 | if not defined INNOSETUP if exist "%SystemDrive%\Inno Setup %%~v\ISCC.exe" set INNOSETUP="%SystemDrive%\Inno Setup %%~v\ISCC.exe" 115 | ) 116 | if not defined INNOSETUP echo build.cmd: Can't find InnoSetup! & exit /b 1 117 | echo build.cmd: Found InnoSetup at: %INNOSETUP% 118 | 119 | rem Build installer 120 | 121 | if exist setup.exe del setup.exe 122 | if exist setup.exe exit /b 1 123 | 124 | if defined SIGN %INNOSETUP% /dSIGN "/Ssleepy=$q%SIGNTOOL%$q sign /n $q%SIGN%$q /a $p /t http://time.certum.pl/ $f" installer.iss 125 | if not defined SIGN %INNOSETUP% installer.iss 126 | if errorlevel 1 exit /b 1 127 | if not exist setup.exe exit /b 1 128 | 129 | rem Package AppVeyor symbol archive artifact 130 | 131 | if defined APPVEYOR !7ZIP! a symbols.7z "obj\*\Release\sleepy.pdb" "thirdparty\wine\dlls\dbghelp\vs\bin\*\*\dbghelpw.pdb" 132 | 133 | echo build.cmd: Done! 134 | -------------------------------------------------------------------------------- /dbghelp_x64/dbghelpms.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/dbghelp_x64/dbghelpms.dll -------------------------------------------------------------------------------- /dbghelp_x64/dbghelpms6.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/dbghelp_x64/dbghelpms6.dll -------------------------------------------------------------------------------- /dbghelp_x64/srcsrv.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/dbghelp_x64/srcsrv.dll -------------------------------------------------------------------------------- /dbghelp_x64/symsrv.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/dbghelp_x64/symsrv.dll -------------------------------------------------------------------------------- /dbghelp_x64/symsrv.yes: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /dbghelp_x86/dbghelpms.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/dbghelp_x86/dbghelpms.dll -------------------------------------------------------------------------------- /dbghelp_x86/dbghelpms6.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/dbghelp_x86/dbghelpms6.dll -------------------------------------------------------------------------------- /dbghelp_x86/srcsrv.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/dbghelp_x86/srcsrv.dll -------------------------------------------------------------------------------- /dbghelp_x86/symsrv.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/dbghelp_x86/symsrv.dll -------------------------------------------------------------------------------- /dbghelp_x86/symsrv.yes: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | #define 2 | #if 3 | #else 4 | #endif 5 | #elif 6 | #include 7 | #ifdef 8 | #ifndef 9 | #warning 10 | #error 11 | #pragma 12 | __alignof 13 | __asm 14 | __assume 15 | __based 16 | __cdecl 17 | __declspec 18 | __event 19 | __except 20 | __fastcall 21 | __finally 22 | __forceinline 23 | __identifier 24 | __if_exists 25 | __if_not_exists 26 | __inline 27 | __int8 28 | __int16 29 | __int32 30 | __int64 31 | __interface 32 | __leave 33 | __m64 34 | __m128 35 | __m128d 36 | __m128i 37 | __multiple_inheritance 38 | __noop 39 | __raise 40 | __single_inheritance 41 | __stdcall 42 | __super 43 | __try 44 | __except 45 | __try 46 | __finally 47 | __uuidof 48 | __virtual_inheritance 49 | __w64 50 | bool 51 | break 52 | case 53 | catch 54 | char 55 | class 56 | const 57 | const_cast 58 | continue 59 | default 60 | delete 61 | do 62 | double 63 | dynamic_cast 64 | else 65 | enum 66 | explicit 67 | extern 68 | false 69 | float 70 | for 71 | friend 72 | goto 73 | if 74 | inline 75 | int 76 | long 77 | mutable 78 | namespace 79 | new 80 | operator 81 | private 82 | protected 83 | public 84 | register 85 | reinterpret_cast 86 | return 87 | short 88 | signed 89 | sizeof 90 | static 91 | static_cast 92 | struct 93 | switch 94 | template 95 | this 96 | throw 97 | true 98 | try 99 | typedef 100 | typeid 101 | typename 102 | union 103 | unsigned 104 | using 105 | virtual 106 | void 107 | volatile 108 | __wchar_t 109 | wchar_t 110 | while 111 | -------------------------------------------------------------------------------- /osfunctions.txt: -------------------------------------------------------------------------------- 1 | fopen 2 | fclose 3 | fread 4 | fwrite 5 | fprintf 6 | fgets 7 | feof 8 | ferror 9 | fflush 10 | fgetpos 11 | fgetc 12 | fputc 13 | fputs 14 | ftell 15 | fseek 16 | fscanf 17 | vfscanf 18 | puts 19 | sprintf 20 | printf 21 | remove 22 | rename 23 | rewind 24 | 25 | malloc 26 | free 27 | calloc 28 | realloc 29 | sscanf 30 | vscanf 31 | 32 | system 33 | getenv 34 | atof 35 | atoi 36 | atol 37 | strtod 38 | strtol 39 | strtoul 40 | strdup 41 | 42 | time 43 | 44 | operator new 45 | operator delete 46 | 47 | D3DXCompileShaderExA 48 | D3DXCompileShaderExW 49 | -------------------------------------------------------------------------------- /osmodules.txt: -------------------------------------------------------------------------------- 1 | ntdll 2 | kernel32 3 | kernelbase 4 | user32 5 | hal 6 | gdi32 7 | comctl32 8 | d3d9 9 | rpcrt4 10 | advapi32 11 | dwmapi 12 | nvd3dum 13 | nvd3dumx 14 | uxtheme 15 | 16 | msvcrt 17 | msvcr70 18 | msvcr71 19 | msvcr80 20 | msvcr81 21 | msvcr90 22 | msvcr91 23 | msvcr70d 24 | msvcr71d 25 | msvcr80d 26 | msvcr81d 27 | msvcr90d 28 | msvcr91d 29 | -------------------------------------------------------------------------------- /src/appinfo.h: -------------------------------------------------------------------------------- 1 | #define APPNAME "Very Sleepy" 2 | 3 | // The VERSION string is in version.h, which is generated 4 | // by gen_version.bat from git tags. 5 | 6 | // These should be updated only in the commits 7 | // tagging a new version. 8 | #define VERSION_MAJOR 0 9 | #define VERSION_MINOR 92 10 | 11 | #define VENDOR "codersnotes.com" 12 | 13 | #define APPURL "http://www.codersnotes.com/sleepy/" 14 | #define GITURL "https://github.com/VerySleepy/verysleepy" 15 | 16 | // Update this whenever backwards-incompatible changes 17 | // are made to the profiling results file format. 18 | #define FORMAT_VERSION "0.92" 19 | -------------------------------------------------------------------------------- /src/copyfiles.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | rem This batch file copies additional DLLs to the obj\ directory, 4 | rem so that you can run a functional Very Sleepy right from Visual Studio. 5 | rem It is automatically called as a PostBuildEvent from sleepy.vcxproj. 6 | 7 | set CONFIGURATION=%1 8 | set PLATFORM=%2 9 | 10 | set DEST=obj\%PLATFORM%\%CONFIGURATION%\ 11 | 12 | if %PLATFORM%==Win32 set PLATFORM_X=x86 13 | if %PLATFORM%==x64 set PLATFORM_X=x64 14 | 15 | set DBGHELPERS=dbghelp_%PLATFORM_X% 16 | copy /y %DBGHELPERS%\*.* %DEST% 17 | if errorlevel 1 ((@echo Failed to copy dbghelp_*) & (exit /b 1)) 18 | 19 | if not exist "%DBGHELPERS%\dbghelpw.dll" copy /y "thirdparty\wine\dlls\dbghelp\vs\bin\%PLATFORM%\%CONFIGURATION%\dbghelpw.dll" "%DEST%" 20 | if errorlevel 1 ((@echo Failed to copy dbghelpw.dll) & (exit /b 1)) 21 | if %PLATFORM%==x64 if not exist "%DBGHELPERS%\dbghelpw_wow64.dll" copy /y "thirdparty\wine\dlls\dbghelp\vs\bin\%PLATFORM%\%CONFIGURATION% - Wow64\dbghelpw.dll" "%DEST%\dbghelpw_wow64.dll" 22 | if errorlevel 1 ((@echo Failed to copy dbghelpw_wow64.dll) & (exit /b 1)) 23 | 24 | if %PLATFORM%==Win32 set PLATFORM_BITS=32 25 | if %PLATFORM%==x64 set PLATFORM_BITS=64 26 | 27 | if not exist "%DBGHELPERS%\dbghelpdr.dll" copy "thirdparty\drmingw_build_%PLATFORM_BITS%\bin\mgwhelp.dll" "%DEST%\dbghelpdr.dll" 28 | if errorlevel 1 ((@echo Failed to copy mgwhelp.dll : dbghelpdr.dll) & (exit /b 1)) 29 | 30 | if not defined VCINSTALLDIR if defined VS120COMNTOOLS set VCINSTALLDIR=%VS120COMNTOOLS%\..\..\VC 31 | for %%D in (msvcr120.dll msvcp120.dll) do copy "%VCINSTALLDIR%\redist\%PLATFORM_X%\Microsoft.VC120.CRT\%%D" "%DEST%\%%D" 32 | if errorlevel 1 echo copyfiles.bat: Warning: couldn't copy the C/C++ runtime DLLs 33 | 34 | copy /y "src\crashback\crashreport\bin\%PLATFORM%\%CONFIGURATION%\crashreport.exe" "%DEST%" 35 | if errorlevel 1 ((@echo Failed to copy crashreport.exe) & (exit /b 1)) 36 | -------------------------------------------------------------------------------- /src/crashback/.gitignore: -------------------------------------------------------------------------------- 1 | obj/ 2 | bin/ 3 | -------------------------------------------------------------------------------- /src/crashback/badapp/badapp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../client/crashback.h" 4 | 5 | int *x = NULL; 6 | 7 | void dosomething() 8 | { 9 | *x = 4; 10 | } 11 | 12 | int main() 13 | { 14 | cbStartup(); 15 | 16 | dosomething(); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/crashback/client/client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../crashreport/crashreport.h" 6 | 7 | HANDLE cbLock = NULL; 8 | CbReport *cbReportData = NULL; 9 | wchar_t cbShareName[256]; 10 | wchar_t cbReportExePath[MAX_PATH] = L""; 11 | wchar_t cbReportExeDir[MAX_PATH] = L""; 12 | wchar_t cbReportCmdLine[1024] = L""; 13 | char cbProgName[256] = ""; 14 | char cbCmdLine[1024] = ""; 15 | EXCEPTION_POINTERS cbTmpExceptionPtrs; 16 | EXCEPTION_RECORD cbTmpExceptionRecord; 17 | CONTEXT cbTmpContext; 18 | 19 | void cbGetExceptionPointers() 20 | { 21 | CONTEXT context; 22 | memset( &context, 0, sizeof(CONTEXT) ); 23 | 24 | #ifdef _X86_ 25 | __asm { 26 | mov dword ptr [context.Eax], eax 27 | mov dword ptr [context.Ecx], ecx 28 | mov dword ptr [context.Edx], edx 29 | mov dword ptr [context.Ebx], ebx 30 | mov dword ptr [context.Esi], esi 31 | mov dword ptr [context.Edi], edi 32 | mov word ptr [context.SegSs], ss 33 | mov word ptr [context.SegCs], cs 34 | mov word ptr [context.SegDs], ds 35 | mov word ptr [context.SegEs], es 36 | mov word ptr [context.SegFs], fs 37 | mov word ptr [context.SegGs], gs 38 | pushfd 39 | pop [context.EFlags] 40 | } 41 | 42 | context.ContextFlags = CONTEXT_CONTROL; 43 | context.Eip = (ULONG)_ReturnAddress(); 44 | context.Esp = (ULONG)_AddressOfReturnAddress(); 45 | context.Ebp = *((ULONG *)_AddressOfReturnAddress()-1); 46 | 47 | #elif defined (_IA64_) || defined (_AMD64_) 48 | RtlCaptureContext( &context ); 49 | #else 50 | #error 51 | #endif 52 | 53 | memcpy( &cbTmpContext, &context, sizeof(CONTEXT) ); 54 | 55 | ZeroMemory( &cbTmpExceptionRecord, sizeof(EXCEPTION_RECORD) ); 56 | cbTmpExceptionRecord.ExceptionCode = 0; 57 | cbTmpExceptionRecord.ExceptionAddress = _ReturnAddress(); 58 | 59 | cbReportData->exceptionPtrs = &cbTmpExceptionPtrs; 60 | cbTmpExceptionPtrs.ExceptionRecord = &cbTmpExceptionRecord; 61 | cbTmpExceptionPtrs.ContextRecord = &cbTmpContext; 62 | } 63 | 64 | void cbReport( CbCrashType type, EXCEPTION_POINTERS *excep ) 65 | { 66 | // Crash handler. 67 | // We try to minimize the amount of code in here, 68 | // as the application may/will be in an unstable state. 69 | 70 | // If we have exception data, use it, otherwise make our own. 71 | if ( excep ) 72 | { 73 | cbReportData->exceptionPtrs = excep; 74 | } else { 75 | cbGetExceptionPointers(); 76 | cbReportData->exceptionPtrs = &cbTmpExceptionPtrs; 77 | } 78 | 79 | // Get some info. 80 | cbReportData->type = type; 81 | cbReportData->threadId = GetCurrentThreadId(); 82 | strcpy_s( cbReportData->programName, 32, cbProgName ); 83 | strcpy_s( cbReportData->cmdLine, 1024, cbCmdLine ); 84 | 85 | // Launch the crash reporter. If it fails, never mind. 86 | STARTUPINFO si = { 0 }; 87 | PROCESS_INFORMATION pi = { 0 }; 88 | si.cb = sizeof(si); 89 | if ( CreateProcess( cbReportExePath, cbReportCmdLine, NULL, NULL, FALSE, 0, NULL, cbReportExeDir, &si, &pi ) ) 90 | { 91 | WaitForSingleObject( pi.hProcess, INFINITE ); 92 | CloseHandle( pi.hProcess ); 93 | CloseHandle( pi.hThread ); 94 | } 95 | } 96 | 97 | LONG CALLBACK cbExceptionHandler( EXCEPTION_POINTERS *excep ) 98 | { 99 | WaitForSingleObject( cbLock, INFINITE ); 100 | cbReport( CB_CRASH_WIN32_SEH, excep ); 101 | TerminateProcess( GetCurrentProcess(), 1 ); 102 | return EXCEPTION_EXECUTE_HANDLER; 103 | } 104 | 105 | void cbTerminateHandler() 106 | { 107 | WaitForSingleObject( cbLock, INFINITE ); 108 | cbReport( CB_CRASH_CRT_TERMINATE, NULL ); 109 | TerminateProcess( GetCurrentProcess(), 1 ); 110 | } 111 | 112 | void cbUnexpectedHandler() 113 | { 114 | WaitForSingleObject( cbLock, INFINITE ); 115 | cbReport( CB_CRASH_CRT_UNEXPECTED, NULL ); 116 | TerminateProcess( GetCurrentProcess(), 1 ); 117 | } 118 | 119 | void cbPureCallHandler() 120 | { 121 | WaitForSingleObject( cbLock, INFINITE ); 122 | cbReport( CB_CRASH_CRT_PURE_VIRTUAL, NULL ); 123 | TerminateProcess( GetCurrentProcess(), 1 ); 124 | } 125 | 126 | void cbInvalidParameterHandler( 127 | const wchar_t *expression, 128 | const wchar_t *function, 129 | const wchar_t *file, 130 | unsigned int line, 131 | uintptr_t pReserved ) 132 | { 133 | WaitForSingleObject( cbLock, INFINITE ); 134 | cbReport( CB_CRASH_CRT_INVALID_PARAMETER, NULL ); 135 | TerminateProcess( GetCurrentProcess(), 1 ); 136 | } 137 | 138 | int cbNewHandler( size_t size ) 139 | { 140 | WaitForSingleObject( cbLock, INFINITE ); 141 | cbReport( CB_CRASH_CRT_NEW, NULL ); 142 | TerminateProcess( GetCurrentProcess(), 1 ); 143 | return 0; 144 | } 145 | 146 | void cbGetProgramName() 147 | { 148 | char tmp[256]; 149 | if ( !GetModuleFileNameA( NULL, tmp, 256 ) ) 150 | strcpy_s( tmp, 256, "unknown" ); 151 | tmp[255] = 0; // ensure it's terminated, just in case 152 | 153 | char *modName = strrchr( tmp, '\\' ); 154 | if ( modName ) 155 | strcpy_s( cbProgName, 256, modName + 1 ); 156 | else 157 | strcpy_s( cbProgName, 256, tmp ); 158 | 159 | // Strip out funny characters, just in case. 160 | for (int n=0;n<256;n++) 161 | { 162 | char &c = cbProgName[n]; 163 | if ( c == 0 ) 164 | break; 165 | 166 | if ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || ( c >= '0' && c <= '9' ) ) 167 | { 168 | // ok 169 | } else { 170 | c = '_'; // bad 171 | } 172 | } 173 | } 174 | 175 | void cbGetCmdLine() 176 | { 177 | strcpy_s( cbCmdLine, 1024, GetCommandLineA() ); 178 | } 179 | 180 | extern "C" void cbStartup() 181 | { 182 | cbLock = CreateMutex( NULL, FALSE, NULL ); 183 | cbReportData = NULL; 184 | 185 | swprintf_s( cbShareName, 256, L"CrashBack_%x", GetCurrentProcessId() ); 186 | 187 | GetModuleFileName( NULL, cbReportExePath, MAX_PATH ); 188 | wcscpy_s( cbReportExeDir, MAX_PATH, cbReportExePath ); 189 | wchar_t *p = wcsrchr( cbReportExeDir, '\\' ); 190 | if ( p ) 191 | *p = 0; 192 | 193 | wcscpy_s( cbReportExePath, MAX_PATH, cbReportExeDir ); 194 | wcscat_s( cbReportExePath, MAX_PATH, L"\\" ); 195 | wcscat_s( cbReportExePath, MAX_PATH, L"crashreport.exe" ); 196 | 197 | // Check that crashreport.exe exists in the app's directory. 198 | if ( GetFileAttributes( cbReportExePath ) == INVALID_FILE_ATTRIBUTES ) 199 | return; 200 | 201 | swprintf_s( cbReportCmdLine, 1024, L"\"%s\" 0x%x", cbReportExePath, GetCurrentProcessId() ); 202 | 203 | cbGetProgramName(); 204 | cbGetCmdLine(); 205 | 206 | // Set up shared memory to communicate with the report handler EXE. 207 | HANDLE hShared = CreateFileMapping( 208 | INVALID_HANDLE_VALUE, // use paging file 209 | NULL, // default security 210 | PAGE_READWRITE, // read/write access 211 | 0, // max. object size 212 | sizeof(CbReport), // buffer size 213 | cbShareName ); // name of mapping object 214 | if ( !hShared ) 215 | return; 216 | 217 | cbReportData = (CbReport *)MapViewOfFile( hShared, FILE_MAP_ALL_ACCESS, 0, 0, sizeof(CbReport) ); 218 | if ( !cbReportData ) 219 | { 220 | CloseHandle( hShared ); 221 | return; 222 | } 223 | 224 | // Register the handlers. 225 | SetUnhandledExceptionFilter( &cbExceptionHandler ); 226 | _set_error_mode( _OUT_TO_STDERR ); 227 | _set_purecall_handler( cbPureCallHandler ); 228 | _set_new_mode( 1 ); // malloc calls the new handler on failure 229 | _set_new_handler( cbNewHandler ); 230 | _set_invalid_parameter_handler( cbInvalidParameterHandler ); 231 | _set_abort_behavior( _CALL_REPORTFAULT, _CALL_REPORTFAULT ); 232 | } 233 | -------------------------------------------------------------------------------- /src/crashback/client/crashback.h: -------------------------------------------------------------------------------- 1 | #ifndef __CRASHBACK_H__ 2 | #define __CRASHBACK_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | void cbStartup(); 9 | 10 | #ifdef __cplusplus 11 | } // extern "C" 12 | #endif 13 | 14 | #endif // __CRASHBACK_H__ 15 | -------------------------------------------------------------------------------- /src/crashback/crashreport/crashreport.h: -------------------------------------------------------------------------------- 1 | #ifndef __CRASHREPORT_H__ 2 | #define __CRASHREPORT_H__ 3 | 4 | /// Reason of the abnormal termination. 5 | /// Update the types array in crashreport.cpp / SaveInfo() 6 | /// when adding new members. 7 | typedef enum 8 | { 9 | CB_CRASH_NONE, // CbReport is invalid 10 | CB_CRASH_WIN32_SEH, 11 | CB_CRASH_CRT_TERMINATE, 12 | CB_CRASH_CRT_UNEXPECTED, 13 | CB_CRASH_CRT_PURE_VIRTUAL, 14 | CB_CRASH_CRT_INVALID_PARAMETER, 15 | CB_CRASH_CRT_NEW, 16 | } CbCrashType; 17 | 18 | /// The structure shared between sleepy.exe and crashback.exe 19 | /// using a shared memory object. 20 | typedef struct 21 | { 22 | CbCrashType type; 23 | char programName[32]; 24 | char cmdLine[1024]; 25 | DWORD threadId; 26 | EXCEPTION_POINTERS *exceptionPtrs; 27 | } CbReport; 28 | 29 | #endif // __CRASHREPORT_H__ 30 | -------------------------------------------------------------------------------- /src/crashback/crashreport/crashreport.rc: -------------------------------------------------------------------------------- 1 | #include 2 | #include "resource.h" 3 | 4 | IDD_CRASH DIALOG 0, 0, 250, 115 5 | STYLE DS_MODALFRAME | DS_CENTER | DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU 6 | CAPTION "Error Reporter" 7 | FONT 8, "MS Shell Dlg" 8 | BEGIN 9 | CONTROL "", ID_ICON, STATIC, SS_ICON, 10, 10, 32, 32 10 | LTEXT "The program has stopped working.\nWould you like to send an error report to the developer?\n\nNo personal information is contained, only the state of the program at the time of the crash.\n\nThese reports actually do help, so please send one!\n", 11 | -1, 40, 10, 190, 100 12 | 13 | CONTROL "", ID_PROGRESS, "msctls_progress32", 0x8, 40, 75, 203, 12 14 | 15 | CONTROL "Examine...", ID_EXAMINE, "LINK", 0, 10, 98, 50, 14 16 | 17 | DEFPUSHBUTTON "Send", IDOK, 138, 95, 50, 14 18 | PUSHBUTTON "Don't send", IDCANCEL, 193, 95, 50, 14 19 | END 20 | -------------------------------------------------------------------------------- /src/crashback/crashreport/resource.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define IDD_CRASH 1000 4 | #define ID_ICON 1001 5 | #define ID_PROGRESS 1002 6 | #define ID_EXAMINE 1003 7 | -------------------------------------------------------------------------------- /src/crashback/web/crashback.php: -------------------------------------------------------------------------------- 1 | $file) 22 | if ($file["error"] == UPLOAD_ERR_OK) 23 | { 24 | $tmp_name = $file["tmp_name"]; 25 | $filename = $file["name"]; 26 | $filename = basename($filename); 27 | move_uploaded_file($tmp_name, "$dir/$filename"); 28 | $filelist .= $url = "http://" . $_SERVER['HTTP_HOST'] . dirname($_SERVER['REQUEST_URI']) . "/$dir/$filename\n"; 29 | } 30 | 31 | 32 | mail(EMAIL, 'Sleepy Crashback', $filelist); 33 | -------------------------------------------------------------------------------- /src/gen_version.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd /d "%~dp0" 3 | 4 | rem Generate a header file with the exact current version using git tags. 5 | rem This file is ran as a pre-build step for the sleepy and crashreport projects. 6 | 7 | rem Find git 8 | 9 | if not defined GIT for %%a in (git.exe) do if not [%%~$PATH:a] == [] set GIT="%%~$PATH:a" 10 | if not defined GIT if exist "%ProgramFiles(x86)%\Git\bin\git.exe" set GIT="%ProgramFiles(x86)%\Git\bin\git.exe" 11 | if not defined GIT if exist "%ProgramFiles%\Git\bin\git.exe" set GIT="%ProgramFiles%\Git\bin\git.exe" 12 | if not defined GIT if exist "%ProgramW6432%\Git\bin\git.exe" set GIT="%ProgramW6432%\Git\bin\git.exe" 13 | if not defined GIT if exist "%SystemDrive%\Git\bin\git.exe" set GIT="%SystemDrive%\Git\bin\git.exe" 14 | if not defined GIT echo gen_version.bat: Can't find git! & exit /b 1 15 | 16 | rem GitHub for Windows sets the GIT variable to the directory containing 17 | rem git.exe, not git.exe itself. Detect and correct for this. 18 | 19 | if exist "%GIT%git.exe" set GIT="%GIT%git.exe" 20 | if exist "%GIT%\git.exe" set GIT="%GIT%\git.exe" 21 | 22 | echo gen_version.bat: Found git at: %GIT% 23 | 24 | rem Get git-describe output 25 | 26 | echo // Auto-generated by gen_version.bat> version.h.tmp 27 | 28 | for /f %%a in ('%GIT% describe --tags --dirty') do set VERSION=%%a 29 | if errorlevel 1 exit /b 1 30 | if [%VERSION%] == [] exit /b 1 31 | echo #define VERSION "%VERSION:~1%">> version.h.tmp 32 | 33 | rem Generate minor version numbers using the commit count and dirty flag 34 | rem from the git-describe output. These are only used in file versions, 35 | rem will be 0 for official releases, and are usually not visible to users. 36 | 37 | set PATCH=0 38 | for /f "tokens=2 delims=-" %%a in ("%VERSION%") do if not [%%a] == [dirty] set PATCH=%%a 39 | 40 | set DIRTY=0 41 | if "%VERSION:~-6%" == "-dirty" set DIRTY=1 42 | 43 | echo #define VERSION_PATCH %PATCH% >> version.h.tmp 44 | echo #define VERSION_DIRTY %DIRTY% >> version.h.tmp 45 | 46 | rem Only update version.h if it changed, to avoid recompiling every time. 47 | 48 | if not exist version.h goto write 49 | fc version.h version.h.tmp > nul 50 | if errorlevel 1 goto write 51 | del version.h.tmp 52 | goto :eof 53 | 54 | :write 55 | move /Y version.h.tmp version.h 56 | goto :eof 57 | -------------------------------------------------------------------------------- /src/profiler/debugger.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | debugger.cpp 3 | --------------- 4 | 5 | Copyright (C) Richard Mitton 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html.. 22 | =====================================================================*/ 23 | #include "debugger.h" 24 | #include "../utils/mythread.h" 25 | #include 26 | #include 27 | #include 28 | 29 | Debugger::Debugger(DWORD processId_) 30 | : processId(processId_) 31 | , processHandle(NULL) 32 | , debuggingActive(true) 33 | , attached(false) 34 | { 35 | } 36 | 37 | Debugger::~Debugger() 38 | { 39 | if (processHandle) 40 | detach(); 41 | } 42 | 43 | void Debugger::notifyNewThread(DWORD threadId, HANDLE threadHandle) 44 | { 45 | NotifyData data; 46 | data.eventType = NOTIFY_NEW_THREAD; 47 | data.threadHandle = threadHandle; 48 | data.threadId = threadId; 49 | notifyFunc(data); 50 | } 51 | 52 | bool Debugger::attach(std::function notifyFunc_) 53 | { 54 | assert(!processHandle); 55 | assert(!notifyFunc); 56 | assert(notifyFunc_); 57 | assert(knownThreads.empty()); 58 | 59 | notifyFunc = notifyFunc_; 60 | 61 | if (debuggingActive && DebugActiveProcess(processId)) 62 | { 63 | DebugSetProcessKillOnExit(FALSE); 64 | } 65 | else 66 | { 67 | finishAttaching(); 68 | assert(!debuggingActive); 69 | } 70 | 71 | while (!attached) 72 | { 73 | update(); 74 | } 75 | 76 | return true; 77 | } 78 | 79 | void Debugger::detach() 80 | { 81 | assert( processHandle ); 82 | 83 | if (debuggingActive) 84 | deactivateDebugging(); 85 | 86 | notifyFunc = nullptr; 87 | 88 | processHandle = NULL; 89 | } 90 | 91 | void Debugger::update() 92 | { 93 | if (debuggingActive) 94 | { 95 | // While debugger is attached, update it to detect new threads 96 | updateDebugging(); 97 | } 98 | else 99 | { 100 | // If debugging can't attach (e.g., if the target is already being debugged) 101 | // or fails after that, fall back to polling a Toolhelp snapshot to detect threads 102 | updateFromSnapshot(); 103 | } 104 | } 105 | 106 | void Debugger::deactivateDebugging() 107 | { 108 | assert(debuggingActive); 109 | debuggingActive = false; 110 | DebugActiveProcessStop(processId); 111 | } 112 | 113 | void Debugger::finishAttaching() 114 | { 115 | if (attached) 116 | return; 117 | 118 | if (!processHandle) 119 | { 120 | processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); 121 | 122 | if (debuggingActive) 123 | deactivateDebugging(); 124 | } 125 | 126 | // make sure notifications for existing threads have fired at this point 127 | if (!debuggingActive) 128 | updateFromSnapshot(); 129 | 130 | attached = true; 131 | } 132 | 133 | void Debugger::updateFromSnapshot() 134 | { 135 | HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 136 | 137 | THREADENTRY32 thread; 138 | thread.dwSize = sizeof(THREADENTRY32); 139 | 140 | if (Thread32First(snapshot, &thread)) 141 | { 142 | std::map threads; 143 | do 144 | { 145 | if (thread.th32OwnerProcessID != processId) 146 | continue; 147 | 148 | threads.insert(std::make_pair(thread.th32ThreadID, true)); 149 | if (knownThreads.find(thread.th32ThreadID) != knownThreads.end()) 150 | continue; 151 | 152 | HANDLE threadHandle = OpenThread(THREAD_ALL_ACCESS, FALSE, thread.th32ThreadID); 153 | if (threadHandle) 154 | notifyNewThread(thread.th32ThreadID, threadHandle); 155 | 156 | } while (Thread32Next(snapshot, &thread)); 157 | 158 | knownThreads = std::move(threads); 159 | } 160 | 161 | CloseHandle(snapshot); 162 | } 163 | 164 | void Debugger::updateDebugging() 165 | { 166 | assert(debuggingActive); 167 | 168 | for (;;) 169 | { 170 | DEBUG_EVENT dbgEvent; 171 | if (!WaitForDebugEvent(&dbgEvent, 0)) 172 | { 173 | DWORD err = GetLastError(); 174 | if (err != ERROR_SEM_TIMEOUT) 175 | { 176 | deactivateDebugging(); 177 | finishAttaching(); 178 | } 179 | return; 180 | } 181 | ContinueDebugEvent(dbgEvent.dwProcessId, dbgEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED); 182 | 183 | switch (dbgEvent.dwDebugEventCode) 184 | { 185 | case EXCEPTION_DEBUG_EVENT: 186 | switch (dbgEvent.u.Exception.ExceptionRecord.ExceptionCode) 187 | { 188 | case EXCEPTION_BREAKPOINT: 189 | // Debugger attach flow follows the sequence 190 | // CREATE_PROCESS_DEBUG_EVENT, where we get the process handle and the main thread, 191 | // CREATE_THREAD_DEBUG_EVENT for every other thread in existence 192 | // LOAD_DLL_DEBUG_EVENT for every loaded DLL 193 | // finally, EXCEPTION_DEBUG_EVENT with code EXCEPTION_BREAKPOINT as the app is stopped by the OS 194 | finishAttaching(); 195 | break; 196 | } 197 | break; 198 | 199 | case RIP_EVENT: 200 | // Debugging error 201 | deactivateDebugging(); 202 | finishAttaching(); 203 | break; 204 | 205 | case CREATE_PROCESS_DEBUG_EVENT: 206 | assert(!processHandle); 207 | processHandle = dbgEvent.u.CreateProcessInfo.hProcess; 208 | notifyNewThread(dbgEvent.dwThreadId, dbgEvent.u.CreateProcessInfo.hThread); 209 | knownThreads.insert(std::make_pair(dbgEvent.dwThreadId, true)); 210 | // We're not using the image file, close the handle 211 | CloseHandle(dbgEvent.u.CreateProcessInfo.hFile); 212 | break; 213 | 214 | case EXIT_PROCESS_DEBUG_EVENT: 215 | // Display the process's exit code. 216 | break; 217 | 218 | case CREATE_THREAD_DEBUG_EVENT: 219 | knownThreads.insert(std::make_pair(dbgEvent.dwThreadId, true)); 220 | notifyNewThread(dbgEvent.dwThreadId, dbgEvent.u.CreateThread.hThread); 221 | break; 222 | 223 | case EXIT_THREAD_DEBUG_EVENT: 224 | knownThreads.erase(dbgEvent.dwThreadId); 225 | break; 226 | 227 | case LOAD_DLL_DEBUG_EVENT: 228 | // We're not using the dll file, close the handle 229 | CloseHandle(dbgEvent.u.LoadDll.hFile); 230 | break; 231 | 232 | case UNLOAD_DLL_DEBUG_EVENT: 233 | // Display a message that the DLL has been unloaded. 234 | break; 235 | 236 | case OUTPUT_DEBUG_STRING_EVENT: 237 | // Display the output debugging string. 238 | break; 239 | } 240 | } 241 | } 242 | 243 | -------------------------------------------------------------------------------- /src/profiler/debugger.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | symbolinfo.h 3 | ------------ 4 | 5 | Copyright (C) Richard Mitton 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html.. 22 | =====================================================================*/ 23 | #ifndef __DEBUGGER_H_666_ 24 | #define __DEBUGGER_H_666_ 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | class Debugger 31 | { 32 | public: 33 | enum NotifyEvent 34 | { 35 | NOTIFY_NEW_THREAD, 36 | }; 37 | 38 | struct NotifyData 39 | { 40 | NotifyEvent eventType; 41 | HANDLE threadHandle; 42 | DWORD threadId; 43 | }; 44 | 45 | Debugger(DWORD processId); 46 | ~Debugger(); 47 | 48 | bool attach(std::function notifyFunc); 49 | void detach(); 50 | 51 | void update(); 52 | protected: 53 | DWORD processId; 54 | HANDLE processHandle; 55 | std::function notifyFunc; 56 | std::map knownThreads; 57 | bool debuggingActive; 58 | bool attached; 59 | 60 | void notifyNewThread(DWORD threadId, HANDLE threadHandle); 61 | 62 | void finishAttaching(); 63 | 64 | void updateFromSnapshot(); 65 | void updateDebugging(); 66 | 67 | void deactivateDebugging(); 68 | 69 | }; 70 | 71 | #endif // __DEBUGGER_H_666_ 72 | -------------------------------------------------------------------------------- /src/profiler/processinfo.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | processinfo.cpp 3 | --------------- 4 | File created by ClassTemplate on Sun Mar 20 03:22:27 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | Copyright (C) 2015 Ashod Nakashian 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 2 12 | of the License, or (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 | 23 | http://www.gnu.org/copyleft/gpl.html.. 24 | =====================================================================*/ 25 | #include "processinfo.h" 26 | 27 | #include "../utils/osutils.h" 28 | #include "../utils/except.h" 29 | #include 30 | #include 31 | 32 | ProcessInfo::ProcessInfo(DWORD id_, const std::wstring& name_, HANDLE process_handle_) 33 | : id(id_), 34 | name(name_), 35 | process_handle(process_handle_) 36 | { 37 | prevKernelTime.dwHighDateTime = prevKernelTime.dwLowDateTime = 0; 38 | prevUserTime.dwHighDateTime = prevUserTime.dwLowDateTime = 0; 39 | cpuUsage = -1; 40 | #ifdef _WIN64 41 | is64Bits = Is64BitProcess(process_handle); 42 | #endif 43 | } 44 | 45 | ProcessInfo::~ProcessInfo() 46 | { 47 | } 48 | 49 | void ProcessInfo::enumProcesses(std::vector& processes_out) 50 | { 51 | HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPTHREAD, 0); 52 | 53 | PROCESSENTRY32 processinfo = {0}; 54 | processinfo.dwSize = sizeof(PROCESSENTRY32); 55 | 56 | if (Process32First(snapshot, &processinfo)) 57 | { 58 | do 59 | { 60 | const DWORD process_id = processinfo.th32ProcessID; 61 | 62 | // Don't allow profiling our own process. Bad things happen. 63 | if (process_id == GetCurrentProcessId()) 64 | { 65 | continue; 66 | } 67 | 68 | //------------------------------------------------------------------------ 69 | //Get the actual handle of the process 70 | //------------------------------------------------------------------------ 71 | const HANDLE process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, process_id); 72 | 73 | // Skip processes we don't have permission to. 74 | if (process_handle == NULL) 75 | { 76 | continue; 77 | } 78 | 79 | if (!CanProfileProcess(process_handle)) 80 | { 81 | CloseHandle(process_handle); 82 | continue; 83 | } 84 | 85 | const std::wstring processname = processinfo.szExeFile; 86 | processes_out.push_back(ProcessInfo(process_id, processname, process_handle)); 87 | 88 | processinfo.dwSize = sizeof(PROCESSENTRY32); 89 | } 90 | while(Process32Next(snapshot, &processinfo)); 91 | } 92 | 93 | //------------------------------------------------------------------------ 94 | //process threads 95 | //------------------------------------------------------------------------ 96 | THREADENTRY32 threadinfo; 97 | threadinfo.dwSize = sizeof(THREADENTRY32); 98 | 99 | if(Thread32First(snapshot, &threadinfo)) 100 | { 101 | do 102 | { 103 | const DWORD owner_process_id = threadinfo.th32OwnerProcessID; 104 | 105 | for(unsigned int i=0; i allProcesses; 128 | enumProcesses(allProcesses); 129 | for (size_t i=0; i < allProcesses.size(); i++) 130 | { 131 | auto process = allProcesses[i]; 132 | if(process.getID() == process_id) 133 | return process; 134 | } 135 | throw SleepyException("Could not found process with specified id: " + std::to_string((unsigned long long) process_id)); 136 | } -------------------------------------------------------------------------------- /src/profiler/processinfo.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | processinfo.h 3 | ------------- 4 | File created by ClassTemplate on Sun Mar 20 03:22:27 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html.. 23 | =====================================================================*/ 24 | #ifndef __PROCESSINFO_H_666_ 25 | #define __PROCESSINFO_H_666_ 26 | 27 | #include 28 | #include "threadinfo.h" 29 | #include 30 | 31 | /*===================================================================== 32 | ProcessInfo 33 | ----------- 34 | Info about a process running on the system 35 | =====================================================================*/ 36 | class ProcessInfo 37 | { 38 | public: 39 | /*===================================================================== 40 | ProcessInfo 41 | ----------- 42 | 43 | =====================================================================*/ 44 | ProcessInfo(DWORD id, const std::wstring& name, HANDLE process_handle); 45 | 46 | ~ProcessInfo(); 47 | 48 | 49 | 50 | static void enumProcesses(std::vector& processes_out); 51 | static ProcessInfo FindProcessById(DWORD process_id); 52 | 53 | std::vector threads; 54 | 55 | const std::wstring& getName() const { return name; } 56 | const DWORD getID() const { return id; } 57 | HANDLE getProcessHandle() const { return process_handle; } 58 | #ifdef _WIN64 59 | bool getIs64Bits() const { return is64Bits; } 60 | #endif 61 | FILETIME prevKernelTime, prevUserTime; 62 | int cpuUsage; 63 | __int64 totalCpuTimeMs; 64 | 65 | private: 66 | std::wstring name; 67 | DWORD id; 68 | HANDLE process_handle; 69 | #ifdef _WIN64 70 | bool is64Bits; 71 | #endif 72 | }; 73 | 74 | 75 | 76 | #endif //__PROCESSINFO_H_666_ 77 | -------------------------------------------------------------------------------- /src/profiler/profiler.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | profiler.h 3 | ---------- 4 | File created by ClassTemplate on Thu Feb 24 19:00:30 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | Copyright (C) 2015 Ashod Nakashian 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 2 12 | of the License, or (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 | 23 | http://www.gnu.org/copyleft/gpl.html.. 24 | =====================================================================*/ 25 | 26 | #pragma once 27 | #ifndef __PROFILER_H_666_ 28 | #define __PROFILER_H_666_ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | //64 bit mode: 37 | #if defined(_WIN64) 38 | typedef unsigned long long PROFILER_ADDR; 39 | #else 40 | //32 bit mode: 41 | typedef unsigned int PROFILER_ADDR; 42 | #endif 43 | 44 | typedef double SAMPLE_TYPE; 45 | class SymbolInfo; 46 | 47 | #define MAX_CALLSTACK_LEVELS 256 48 | 49 | class CallStack 50 | { 51 | public: 52 | size_t depth; 53 | DWORD thread_id; 54 | PROFILER_ADDR addr[MAX_CALLSTACK_LEVELS]; 55 | 56 | bool isBefore(const CallStack &other, bool considerThreadId) const 57 | { 58 | if (depth != other.depth) 59 | return (depth < other.depth); 60 | 61 | for (size_t n = 0; n < depth; n++) 62 | { 63 | if (addr[n] < other.addr[n]) 64 | return true; 65 | if (addr[n] > other.addr[n]) 66 | return false; 67 | } 68 | 69 | if (considerThreadId) 70 | return thread_id < other.thread_id; 71 | 72 | return false; 73 | } 74 | 75 | bool operator < (const CallStack &other) const 76 | { 77 | return isBefore(other, true); 78 | } 79 | }; 80 | 81 | class ProfilerExcep 82 | { 83 | public: 84 | ProfilerExcep(const std::wstring& s_) : s(s_) {} 85 | ~ProfilerExcep(){} 86 | 87 | const std::wstring& what() const { return s; } 88 | private: 89 | std::wstring s; 90 | }; 91 | 92 | /*===================================================================== 93 | Profiler 94 | -------- 95 | does the EIP sampling 96 | =====================================================================*/ 97 | class Profiler 98 | { 99 | public: 100 | /*===================================================================== 101 | Profiler 102 | -------- 103 | 104 | =====================================================================*/ 105 | // DE: 20090325: Profiler no longer owns callstack since it is shared between multipler profilers 106 | Profiler(HANDLE target_process, HANDLE target_thread, DWORD target_thread_id, 107 | std::map& callstacks); 108 | 109 | // DE: 20090325: Need copy constructor since it is put in a std::vector 110 | Profiler(const Profiler& iOther); 111 | // DE: 20090325: Need copy assignement since it is put in a std::vector 112 | Profiler& operator=(const Profiler& iOther); 113 | 114 | ~Profiler(); 115 | 116 | // DE: 20090325: Profiler no longer owns callstack and flatcounts since it is shared between multipler profilers 117 | // AA: 20210821: Removed flatcounts since their contents can be reconstructed on load by iterating over 118 | // callstack top address samples and aggregating times for equal keys 119 | std::map *callstacks; 120 | const bool is64BitProcess; 121 | 122 | bool sampleTarget(SAMPLE_TYPE timeSpent, SymbolInfo *syminfo);//throws ProfilerExcep 123 | bool targetExited() const; 124 | 125 | //void saveIPs(std::ostream& stream);//write IP values to a stream 126 | 127 | HANDLE getTarget(){ return target_thread; } 128 | private: 129 | HANDLE target_process, target_thread; 130 | DWORD target_thread_id; 131 | }; 132 | 133 | 134 | 135 | #endif //__PROFILER_H_666_ 136 | -------------------------------------------------------------------------------- /src/profiler/profilerthread.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | profilerthread.h 3 | ---------------- 4 | File created by ClassTemplate on Thu Feb 24 19:29:41 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | Copyright (C) 2015 Ashod Nakashian 8 | 9 | This program is free software; you can redistribute it and/or 10 | modify it under the terms of the GNU General Public License 11 | as published by the Free Software Foundation; either version 2 12 | of the License, or (at your option) any later version. 13 | 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | 19 | You should have received a copy of the GNU General Public License 20 | along with this program; if not, write to the Free Software 21 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 22 | 23 | http://www.gnu.org/copyleft/gpl.html.. 24 | =====================================================================*/ 25 | 26 | #pragma once 27 | #ifndef __PROFILERTHREAD_H_666_ 28 | #define __PROFILERTHREAD_H_666_ 29 | 30 | #include "../utils/mythread.h" 31 | #include "profiler.h" 32 | #include "symbolinfo.h" 33 | 34 | // DE: 20090325 Profiler thread now has a vector of threads to profile 35 | #include 36 | 37 | class Debugger; 38 | 39 | /*===================================================================== 40 | ProfilerThread 41 | -------------- 42 | a thread that runs the profiler at a certain frequency 43 | =====================================================================*/ 44 | class ProfilerThread : public MyThread 45 | { 46 | public: 47 | /*===================================================================== 48 | ProfilerThread 49 | -------------- 50 | HANDLE target_thread: 51 | handle to thread to profile. 52 | 53 | int num_samples: 54 | number of samples to take. Takes ~1000 samples per sec. 55 | The greater the number of samples, the more accurate the profile. 56 | Use at least 40000 or so. 57 | 58 | =====================================================================*/ 59 | // DE: 20090325 Profiler thread now has a vector of threads to profile 60 | // RM: 20130614 Profiler time can now be limited (-1 = until cancelled) 61 | ProfilerThread(HANDLE target_process, const std::vector& target_threads, SymbolInfo *sym_info, Debugger *debugger); 62 | 63 | virtual ~ProfilerThread(); 64 | 65 | 66 | //call this to start profiling. 67 | virtual void run(); 68 | 69 | int getNumThreadsRunning() const { return numThreadsRunning; } 70 | bool getDone() const { return done; } 71 | bool getFailed() const { return failed; } 72 | const wchar_t* getStatus() const { return status; } 73 | SAMPLE_TYPE getDuration() const { return duration; } 74 | int getSampleProgress() const { return numsamplessofar; } 75 | void getSymbolsProgress(int *permille, std::wstring *stage) const { *permille = symbolsPermille; *stage = symbolsStage; } 76 | const std::wstring &getFilename() const { return filename; } 77 | void setPaused(bool paused_) { paused = paused_; } 78 | void cancel() { cancelled = true; } 79 | void commitSuicide() { commit_suicide = true; } 80 | 81 | void sample(const SAMPLE_TYPE timeSpent);//for internal use. 82 | private: 83 | //std::wstring demangleProcName(const std::wstring& mangled_name); 84 | void error(const std::wstring& what); 85 | 86 | void sampleLoop(); 87 | void saveData(); 88 | 89 | std::wstring symbolsStage; 90 | int symbolsPermille, symbolsDone, symbolsTotal; 91 | void beginProgress(std::wstring stage, int total=0); 92 | bool updateProgress(); 93 | 94 | // DE: 20090325 callstacks are shared for all threads to profile 95 | std::map callstacks; 96 | 97 | // DE: 20090325 one Profiler instance per thread to profile 98 | std::vector profilers; 99 | Debugger *debugger; 100 | SAMPLE_TYPE duration; 101 | //int numsamples; 102 | const wchar_t* status; 103 | int numsamplessofar; 104 | int numThreadsRunning; 105 | bool done; 106 | bool paused; 107 | bool failed; 108 | bool cancelled; 109 | bool commit_suicide; 110 | HANDLE target_process; 111 | std::map thread_names; 112 | std::wstring filename; 113 | std::wstring minidump; 114 | SymbolInfo *sym_info; 115 | 116 | DWORD startTick; 117 | }; 118 | 119 | 120 | 121 | #endif //__PROFILERTHREAD_H_666_ 122 | -------------------------------------------------------------------------------- /src/profiler/symbolinfo.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | symbolinfo.h 3 | ------------ 4 | File created by ClassTemplate on Sat Mar 05 19:10:20 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html.. 23 | =====================================================================*/ 24 | #ifndef __SYMBOLINFO_H_666_ 25 | #define __SYMBOLINFO_H_666_ 26 | 27 | 28 | #include 29 | #include 30 | #include 31 | #include "profiler.h" 32 | 33 | typedef void SymLogFn(const wchar_t *text); 34 | 35 | struct DbgHelp; 36 | 37 | class Module 38 | { 39 | public: 40 | Module(PROFILER_ADDR base_addr_, const std::wstring& name_, DbgHelp *dbghelp_) 41 | { 42 | base_addr = base_addr_; 43 | name = name_; 44 | dbghelp = dbghelp_; 45 | } 46 | PROFILER_ADDR base_addr; 47 | std::wstring name; 48 | DbgHelp *dbghelp; 49 | }; 50 | 51 | /*===================================================================== 52 | SymbolInfo 53 | ---------- 54 | Wrapper around some DbgHelp API stuff. 55 | =====================================================================*/ 56 | class SymbolInfo 57 | { 58 | public: 59 | SymbolInfo(); 60 | ~SymbolInfo(); 61 | 62 | void loadSymbols(HANDLE process_handle, bool download);//throws SymbolInfoExcep 63 | std::wstring saveMinidump(); 64 | 65 | Module *getModuleForAddr(PROFILER_ADDR addr); 66 | const std::wstring getModuleNameForAddr(PROFILER_ADDR addr); 67 | const std::wstring getProcForAddr(PROFILER_ADDR addr, std::wstring& procfilepath_out, int& proclinenum_out); 68 | 69 | void getLineForAddr(PROFILER_ADDR addr, std::wstring& filepath_out, int& linenum_out); 70 | 71 | HANDLE process_handle; 72 | 73 | private: 74 | std::vector modules; 75 | bool is64BitProcess; 76 | 77 | void addModule(const Module& module); 78 | void sortModules(); 79 | 80 | friend BOOL CALLBACK EnumModules(PCWSTR ModuleName, DWORD64 BaseOfDll, PVOID UserContext); 81 | void loadSymbolsUsing(DbgHelp* dbgHelp, const std::wstring& sympath);//throws SymbolInfoExcep 82 | DbgHelp* getGccDbgHelp(); 83 | }; 84 | 85 | extern SymLogFn *g_symLog; 86 | 87 | #endif //__SYMBOLINFO_H_666_ 88 | -------------------------------------------------------------------------------- /src/profiler/threadinfo.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | threadinfo.cpp 3 | -------------- 4 | File created by ClassTemplate on Sun Mar 20 03:22:37 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html.. 23 | =====================================================================*/ 24 | #include "threadinfo.h" 25 | 26 | static __int64 getDiff(FILETIME before, FILETIME after) 27 | { 28 | __int64 i0 = (__int64(before.dwHighDateTime) << 32) + before.dwLowDateTime; 29 | __int64 i1 = (__int64(after.dwHighDateTime) << 32) + after.dwLowDateTime; 30 | return i1 - i0; 31 | } 32 | 33 | static __int64 getTotal(FILETIME time) 34 | { 35 | return (__int64(time.dwHighDateTime) << 32) + time.dwLowDateTime; 36 | } 37 | 38 | typedef HRESULT( WINAPI *GetThreadDescriptionFunc )(HANDLE, PWSTR*); 39 | static GetThreadDescriptionFunc GetThreadDescription_ = reinterpret_cast(GetProcAddress( GetModuleHandle( TEXT( "Kernel32.dll" ) ), "GetThreadDescription" )); 40 | 41 | bool hasThreadDescriptionAPI() 42 | { 43 | // Helper function to let main window decide whether to hide this column 44 | return GetThreadDescription_ != NULL; 45 | } 46 | 47 | std::wstring getThreadDescriptorName(HANDLE thread_handle) 48 | { 49 | std::wstring name = L"-"; 50 | 51 | // Try to use the new thread naming API from Win10 Creators update onwards if we have it 52 | if (GetThreadDescription_) { 53 | PWSTR data; 54 | HRESULT hr = GetThreadDescription_(thread_handle, &data); 55 | if (SUCCEEDED(hr)) { 56 | if (wcslen(data) > 0) 57 | name = data; 58 | LocalFree(data); 59 | } 60 | } 61 | 62 | return name; 63 | } 64 | 65 | // DE: 20090325 Threads now have CPU usage 66 | ThreadInfo::ThreadInfo(DWORD id_, HANDLE thread_handle_) 67 | : id(id_), thread_handle(thread_handle_) 68 | { 69 | prevKernelTime.dwHighDateTime = prevKernelTime.dwLowDateTime = 0; 70 | prevUserTime.dwHighDateTime = prevUserTime.dwLowDateTime = 0; 71 | cpuUsage = -1; 72 | 73 | name = getThreadDescriptorName(thread_handle); 74 | } 75 | 76 | ThreadInfo::~ThreadInfo() 77 | { 78 | } 79 | 80 | bool ThreadInfo::recalcUsage(int sampleTimeDiff) 81 | { 82 | cpuUsage = -1; 83 | totalCpuTimeMs = -1; 84 | 85 | HANDLE thread_handle_ = getThreadHandle(); 86 | if (thread_handle_ == NULL) 87 | return false; 88 | 89 | FILETIME CreationTime, ExitTime, KernelTime, UserTime; 90 | 91 | if (!GetThreadTimes( 92 | thread_handle_, 93 | &CreationTime, 94 | &ExitTime, 95 | &KernelTime, 96 | &UserTime 97 | )) 98 | return false; 99 | 100 | __int64 kernel_diff = getDiff(prevKernelTime, KernelTime); 101 | __int64 user_diff = getDiff(prevUserTime, UserTime); 102 | prevKernelTime = KernelTime; 103 | prevUserTime = UserTime; 104 | 105 | if (sampleTimeDiff > 0) { 106 | __int64 total_diff = ((kernel_diff + user_diff) / 10000) * 100; 107 | cpuUsage = static_cast(total_diff / sampleTimeDiff); 108 | } 109 | totalCpuTimeMs = (getTotal(KernelTime) + getTotal(UserTime)) / 10000; 110 | 111 | return true; 112 | } 113 | -------------------------------------------------------------------------------- /src/profiler/threadinfo.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | threadinfo.h 3 | ------------ 4 | File created by ClassTemplate on Sun Mar 20 03:22:37 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html.. 23 | =====================================================================*/ 24 | #ifndef __THREADINFO_H_666_ 25 | #define __THREADINFO_H_666_ 26 | 27 | 28 | #include 29 | #include 30 | 31 | bool hasThreadDescriptionAPI(); 32 | std::wstring getThreadDescriptorName(HANDLE thread_handle); 33 | 34 | /*===================================================================== 35 | ThreadInfo 36 | ---------- 37 | Info about a thread running on the system 38 | =====================================================================*/ 39 | class ThreadInfo 40 | { 41 | public: 42 | /*===================================================================== 43 | ThreadInfo 44 | ---------- 45 | 46 | =====================================================================*/ 47 | ThreadInfo(DWORD id, HANDLE thread_handle); 48 | 49 | ~ThreadInfo(); 50 | 51 | const DWORD getID() const { return id; } 52 | HANDLE getThreadHandle() const { return thread_handle; } 53 | 54 | const std::wstring& getLocation() const { return location; } 55 | void setLocation(const std::wstring &loc) { location = loc; } 56 | 57 | const std::wstring& getName() const { return name; } 58 | bool recalcUsage(int sampleTimeDiff); 59 | 60 | FILETIME prevKernelTime, prevUserTime; 61 | // DE: 20090325 Threads now have CPU usage 62 | int cpuUsage; 63 | __int64 totalCpuTimeMs; 64 | 65 | private: 66 | std::wstring location; 67 | std::wstring name; 68 | DWORD id; 69 | HANDLE thread_handle; 70 | }; 71 | 72 | 73 | 74 | #endif //__THREADINFO_H_666_ 75 | -------------------------------------------------------------------------------- /src/res/Button-Add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-Add.png -------------------------------------------------------------------------------- /src/res/Button-Down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-Down.png -------------------------------------------------------------------------------- /src/res/Button-Download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-Download.png -------------------------------------------------------------------------------- /src/res/Button-ExportCSV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-ExportCSV.png -------------------------------------------------------------------------------- /src/res/Button-Go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-Go.png -------------------------------------------------------------------------------- /src/res/Button-Next.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-Next.png -------------------------------------------------------------------------------- /src/res/Button-Pause.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-Pause.png -------------------------------------------------------------------------------- /src/res/Button-Previous.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-Previous.png -------------------------------------------------------------------------------- /src/res/Button-ProfileAll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-ProfileAll.png -------------------------------------------------------------------------------- /src/res/Button-ProfileSel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-ProfileSel.png -------------------------------------------------------------------------------- /src/res/Button-Refresh.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-Refresh.png -------------------------------------------------------------------------------- /src/res/Button-Remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-Remove.png -------------------------------------------------------------------------------- /src/res/Button-Up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/Button-Up.png -------------------------------------------------------------------------------- /src/res/sleepy.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VerySleepy/verysleepy/dcec5323ce217b300adfba965c06518071db2034/src/res/sleepy.ico -------------------------------------------------------------------------------- /src/res/sleepy.rc: -------------------------------------------------------------------------------- 1 | #define wxUSE_RC_MANIFEST 1 2 | #define wxUSE_DPI_AWARE_MANIFEST 1 3 | 4 | #include "wx/msw/wx.rc" 5 | 6 | sleepy ICON "sleepy.ico" 7 | 8 | button_next PNG "Button-Next.png" 9 | button_prev PNG "Button-Previous.png" 10 | button_download PNG "Button-Download.png" 11 | button_refresh PNG "Button-Refresh.png" 12 | button_profileall PNG "Button-ProfileAll.png" 13 | button_profilesel PNG "Button-ProfileSel.png" 14 | button_pause PNG "Button-Pause.png" 15 | button_go PNG "Button-Go.png" 16 | button_up PNG "Button-Up.png" 17 | button_down PNG "Button-Down.png" 18 | button_add PNG "Button-Add.png" 19 | button_remove PNG "Button-Remove.png" 20 | button_exportcsv PNG "Button-ExportCSV.png" 21 | 22 | #include "../appinfo.h" 23 | #include "../version.h" 24 | 25 | VS_VERSION_INFO VERSIONINFO 26 | FILEVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,VERSION_DIRTY 27 | PRODUCTVERSION VERSION_MAJOR,VERSION_MINOR,VERSION_PATCH,VERSION_DIRTY 28 | FILEFLAGSMASK 0x3fL 29 | #ifdef _DEBUG 30 | FILEFLAGS VER_DEBUG 31 | #else 32 | FILEFLAGS 0 33 | #endif 34 | FILEOS VOS__WINDOWS32 35 | FILETYPE VFT_APP 36 | FILESUBTYPE 0 37 | BEGIN 38 | BLOCK "StringFileInfo" 39 | BEGIN 40 | BLOCK "040904E4" 41 | BEGIN 42 | VALUE "CompanyName", VENDOR "\0" 43 | VALUE "FileDescription", APPNAME "\0" 44 | VALUE "FileVersion", VERSION "\0" 45 | VALUE "InternalName", "sleepy" "\0" 46 | VALUE "LegalCopyright", "Copyright (C) " VENDOR " and contributors" "\0" 47 | VALUE "OriginalFilename", "sleepy.exe" "\0" 48 | VALUE "ProductName", APPNAME "\0" 49 | VALUE "ProductVersion", VERSION "\0" 50 | END 51 | END 52 | BLOCK "VarFileInfo" 53 | BEGIN 54 | VALUE "Translation", 0x409, 1252 55 | END 56 | END 57 | -------------------------------------------------------------------------------- /src/utils/WoW64.cpp: -------------------------------------------------------------------------------- 1 | #ifdef _WIN64 2 | #define WIN32_LEAN_AND_MEAN 3 | #include 4 | #include "WoW64.h" 5 | 6 | Wow64GetThreadContext_t *fn_Wow64GetThreadContext = (Wow64GetThreadContext_t *)GetProcAddress(GetModuleHandle(L"kernel32"),"Wow64GetThreadContext"); 7 | Wow64SuspendThread_t *fn_Wow64SuspendThread = (Wow64SuspendThread_t *)GetProcAddress(GetModuleHandle(L"kernel32"),"Wow64SuspendThread"); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/utils/WoW64.h: -------------------------------------------------------------------------------- 1 | #if defined(_WIN64) 2 | 3 | // Microsoft added a couple of functions that does not exist on Windows XP 64. 4 | // The function also needs a newer sdk. 5 | // 6 | // To make things easy I add the missing functions using function pointers. 7 | // 8 | //Johan 9 | 10 | #if WINVER < 0x0600 // Already defined on Vista SDKs 11 | 12 | #define WOW64_MAXIMUM_SUPPORTED_EXTENSION 512 13 | #define WOW64_SIZE_OF_80387_REGISTERS 80 14 | 15 | typedef struct _WOW64_FLOATING_SAVE_AREA { 16 | DWORD ControlWord; 17 | DWORD StatusWord; 18 | DWORD TagWord; 19 | DWORD ErrorOffset; 20 | DWORD ErrorSelector; 21 | DWORD DataOffset; 22 | DWORD DataSelector; 23 | BYTE RegisterArea[WOW64_SIZE_OF_80387_REGISTERS]; 24 | DWORD Cr0NpxState; 25 | } WOW64_FLOATING_SAVE_AREA; 26 | 27 | typedef struct _WOW64_CONTEXT { 28 | 29 | // 30 | // The flags values within this flag control the contents of 31 | // a CONTEXT record. 32 | // 33 | // If the context record is used as an input parameter, then 34 | // for each portion of the context record controlled by a flag 35 | // whose value is set, it is assumed that that portion of the 36 | // context record contains valid context. If the context record 37 | // is being used to modify a threads context, then only that 38 | // portion of the threads context will be modified. 39 | // 40 | // If the context record is used as an IN OUT parameter to capture 41 | // the context of a thread, then only those portions of the thread's 42 | // context corresponding to set flags will be returned. 43 | // 44 | // The context record is never used as an OUT only parameter. 45 | // 46 | 47 | DWORD ContextFlags; 48 | 49 | // 50 | // This section is specified/returned if CONTEXT_DEBUG_REGISTERS is 51 | // set in ContextFlags. Note that CONTEXT_DEBUG_REGISTERS is NOT 52 | // included in CONTEXT_FULL. 53 | // 54 | 55 | DWORD Dr0; 56 | DWORD Dr1; 57 | DWORD Dr2; 58 | DWORD Dr3; 59 | DWORD Dr6; 60 | DWORD Dr7; 61 | 62 | // 63 | // This section is specified/returned if the 64 | // ContextFlags word contians the flag CONTEXT_FLOATING_POINT. 65 | // 66 | 67 | WOW64_FLOATING_SAVE_AREA FloatSave; 68 | 69 | // 70 | // This section is specified/returned if the 71 | // ContextFlags word contians the flag CONTEXT_SEGMENTS. 72 | // 73 | 74 | DWORD SegGs; 75 | DWORD SegFs; 76 | DWORD SegEs; 77 | DWORD SegDs; 78 | 79 | // 80 | // This section is specified/returned if the 81 | // ContextFlags word contians the flag CONTEXT_INTEGER. 82 | // 83 | 84 | DWORD Edi; 85 | DWORD Esi; 86 | DWORD Ebx; 87 | DWORD Edx; 88 | DWORD Ecx; 89 | DWORD Eax; 90 | 91 | // 92 | // This section is specified/returned if the 93 | // ContextFlags word contians the flag CONTEXT_CONTROL. 94 | // 95 | 96 | DWORD Ebp; 97 | DWORD Eip; 98 | DWORD SegCs; // MUST BE SANITIZED 99 | DWORD EFlags; // MUST BE SANITIZED 100 | DWORD Esp; 101 | DWORD SegSs; 102 | 103 | // 104 | // This section is specified/returned if the ContextFlags word 105 | // contains the flag CONTEXT_EXTENDED_REGISTERS. 106 | // The format and contexts are processor specific 107 | // 108 | 109 | BYTE ExtendedRegisters[WOW64_MAXIMUM_SUPPORTED_EXTENSION]; 110 | 111 | } WOW64_CONTEXT; 112 | 113 | typedef WOW64_CONTEXT *PWOW64_CONTEXT; 114 | 115 | #define WOW64_CONTEXT_i386 0x00010000 // this assumes that i386 and 116 | #define WOW64_CONTEXT_i486 0x00010000 // i486 have identical context records 117 | 118 | #define WOW64_CONTEXT_CONTROL (WOW64_CONTEXT_i386 | 0x00000001L) // SS:SP, CS:IP, FLAGS, BP 119 | #define WOW64_CONTEXT_INTEGER (WOW64_CONTEXT_i386 | 0x00000002L) // AX, BX, CX, DX, SI, DI 120 | #define WOW64_CONTEXT_SEGMENTS (WOW64_CONTEXT_i386 | 0x00000004L) // DS, ES, FS, GS 121 | #define WOW64_CONTEXT_FLOATING_POINT (WOW64_CONTEXT_i386 | 0x00000008L) // 387 state 122 | #define WOW64_CONTEXT_DEBUG_REGISTERS (WOW64_CONTEXT_i386 | 0x00000010L) // DB 0-3,6,7 123 | #define WOW64_CONTEXT_EXTENDED_REGISTERS (WOW64_CONTEXT_i386 | 0x00000020L) // cpu specific extensions 124 | 125 | #define WOW64_CONTEXT_FULL (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS) 126 | 127 | #define WOW64_CONTEXT_ALL (WOW64_CONTEXT_CONTROL | WOW64_CONTEXT_INTEGER | WOW64_CONTEXT_SEGMENTS | \ 128 | WOW64_CONTEXT_FLOATING_POINT | WOW64_CONTEXT_DEBUG_REGISTERS | \ 129 | WOW64_CONTEXT_EXTENDED_REGISTERS) 130 | 131 | #define WOW64_CONTEXT_XSTATE (WOW64_CONTEXT_i386 | 0x00000040L) 132 | 133 | #endif // WINVER 134 | 135 | typedef BOOL WINAPI Wow64GetThreadContext_t(__in HANDLE hThread,__inout PWOW64_CONTEXT lpContext); 136 | typedef DWORD WINAPI Wow64SuspendThread_t(__in HANDLE hThread); 137 | 138 | extern Wow64GetThreadContext_t *fn_Wow64GetThreadContext; 139 | extern Wow64SuspendThread_t *fn_Wow64SuspendThread; 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /src/utils/container.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | container.h 3 | -------------- 4 | Copyright (C) Vladimir Panteleev 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | http://www.gnu.org/copyleft/gpl.html.. 21 | =====================================================================*/ 22 | 23 | #pragma once 24 | 25 | #include 26 | 27 | /// Find an entry with the specified key and return its value, 28 | /// or, failing that, return a default value. 29 | template 30 | static typename MAP::value_type::second_type map_get(const MAP &map, const typename MAP::key_type &key, const typename MAP::value_type::second_type defaultValue = MAP::value_type::second_type()) 31 | { 32 | MAP::const_iterator i = map.find(key); 33 | if (i == map.end()) 34 | return defaultValue; 35 | return i->second; 36 | } 37 | 38 | /// Add or find an entry to the map with the specified key. 39 | /// Copies true to *pinserted if a new entry was added, false if an existing one was found. 40 | /// Returns a reference to the new/existing value. 41 | template 42 | static typename MAP::value_type::second_type& map_emplace(MAP &map, const typename MAP::key_type &key, bool *pinserted=NULL) 43 | { 44 | auto pair = map.emplace(std::make_pair(key, MAP::value_type::second_type())); 45 | if (pinserted) *pinserted = pair.second; 46 | return pair.first->second; 47 | } 48 | 49 | /// Add or find an entry in a string[id] vector / id[string] map pair, and return its ID. 50 | template 51 | static ID map_string(std::vector &list, std::unordered_map&map, std::wstring key) 52 | { 53 | bool inserted; 54 | ID &id = map_emplace(map, key, &inserted); 55 | if (inserted) // new entry 56 | { 57 | list.push_back(key); 58 | return id = list.size() - 1; 59 | } 60 | else // existing entry 61 | return id; 62 | } 63 | 64 | #include 65 | 66 | /// Nicer wrapper around set::count. 67 | template 68 | static bool set_get(const SET &set, const typename SET::key_type &key) 69 | { 70 | return set.count(key) != 0; 71 | } 72 | 73 | /// Make sure the specified item is / isn't in the set, according to a boolean. 74 | template 75 | static void set_set(SET &set, const typename SET::key_type &key, bool value) 76 | { 77 | if (value) 78 | set.insert(key); 79 | else 80 | { 81 | SET::const_iterator i = set.find(key); 82 | if (i != set.end()) 83 | set.erase(i); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/utils/dbginterface.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | dbginterface.cpp 3 | ------------ 4 | 5 | Copyright (C) Richard Mitton 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #include "dbginterface.h" 24 | #include 25 | #include "except.h" 26 | 27 | DbgHelp dbgHelpMs; 28 | DbgHelp dbgHelpDrMingw; 29 | DbgHelp dbgHelpWine; 30 | DbgHelp dbgHelpWineWow64; 31 | 32 | #define IMPORT(name) *(void **)&dest->name = GetProcAddress(hMod, #name) 33 | 34 | static bool dbgHelpTryLoad(LPCWSTR name, DbgHelp* dest) 35 | { 36 | dest->Name = name; 37 | HMODULE hMod = LoadLibrary(name); 38 | if (!hMod) 39 | return false; 40 | IMPORT(StackWalk64); 41 | IMPORT(SymFunctionTableAccess64); 42 | IMPORT(SymGetModuleBase64); 43 | IMPORT(SymCleanup); 44 | IMPORT(SymEnumerateModulesW64); 45 | IMPORT(SymSetSearchPathW); 46 | IMPORT(SymInitializeW); 47 | IMPORT(SymSetOptions); 48 | IMPORT(SymGetOptions); 49 | IMPORT(SymGetModuleInfoW64); 50 | IMPORT(SymFromAddrW); 51 | IMPORT(SymGetLineFromAddrW64); 52 | IMPORT(SymRegisterCallbackW64); 53 | IMPORT(SymRefreshModuleList); 54 | IMPORT(SymLoadModuleExW); 55 | IMPORT(SymSetDbgPrint); // Custom Wine extension 56 | IMPORT(MiniDumpWriteDump); 57 | dest->Loaded = true; 58 | return true; 59 | } 60 | 61 | static void dbgHelpLoad(LPCWSTR name, DbgHelp* dest, const wxString& description) 62 | { 63 | if (!dbgHelpTryLoad(name, dest)) 64 | wxLogWarning("Could not load " + wxString(name) + ": " + wxSysErrorMsg() + "\n" + description + " will be unavailable."); 65 | } 66 | 67 | bool dbgHelpInit() 68 | { 69 | // Import the Microsoft dbghelp.dll 70 | if (!dbgHelpTryLoad(L"dbghelpms.dll", &dbgHelpMs)) 71 | { 72 | // The latest version of dbghelp.dll requires a 73 | // recent version of Windows to run. If loading 74 | // that fails, fall back to an older version. 75 | dbgHelpLoad(L"dbghelpms6.dll", &dbgHelpMs, "Microsoft debug information"); 76 | } 77 | 78 | // Import the DrMingw dbghelp.dll 79 | dbgHelpLoad(L"dbghelpdr.dll", &dbgHelpDrMingw, "Dr. MinGW debug information"); 80 | 81 | // Import the Wine dbghelp.dll 82 | dbgHelpLoad(L"dbghelpw.dll", &dbgHelpWine, "Wine debug information"); 83 | 84 | #ifdef _WIN64 85 | // Import the Wine Wow64 dbghelp.dll 86 | dbgHelpLoad(L"dbghelpw_wow64.dll", &dbgHelpWineWow64, "WoW64 Wine debug information"); 87 | #endif 88 | 89 | return true; 90 | } 91 | -------------------------------------------------------------------------------- /src/utils/dbginterface.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | dbginterface.h 3 | ---------- 4 | 5 | Copyright (C) Richard Mitton 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #ifndef __DBGINTERFACE_H__ 24 | #define __DBGINTERFACE_H__ 25 | 26 | // Use our own copy of dbghelp.h, to make sure it's the latest version. 27 | #include 28 | #include "..\..\thirdparty\ms\dbghelp.h" 29 | 30 | // We provide a wrapper around the dbghelp functions we need, so that 31 | // we can switch to either the MS or Wine versions at runtime. 32 | 33 | struct DbgHelp 34 | { 35 | BOOL 36 | (WINAPI *StackWalk64)( 37 | __in DWORD MachineType, 38 | __in HANDLE hProcess, 39 | __in HANDLE hThread, 40 | __inout LPSTACKFRAME64 StackFrame, 41 | __inout PVOID ContextRecord, 42 | __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, 43 | __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, 44 | __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, 45 | __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress 46 | ); 47 | 48 | PVOID 49 | (WINAPI *SymFunctionTableAccess64)( 50 | __in HANDLE hProcess, 51 | __in DWORD64 AddrBase 52 | ); 53 | 54 | DWORD64 55 | (WINAPI *SymGetModuleBase64)( 56 | __in HANDLE hProcess, 57 | __in DWORD64 qwAddr 58 | ); 59 | 60 | BOOL 61 | (WINAPI *SymCleanup)( 62 | __in HANDLE hProcess 63 | ); 64 | 65 | BOOL 66 | (WINAPI *SymEnumerateModulesW64)( 67 | __in HANDLE hProcess, 68 | __in PSYM_ENUMMODULES_CALLBACKW64 EnumModulesCallback, 69 | __in_opt PVOID UserContext 70 | ); 71 | 72 | BOOL 73 | (WINAPI *SymSetSearchPathW)( 74 | __in HANDLE hProcess, 75 | __in_opt PCWSTR SearchPath 76 | ); 77 | 78 | BOOL 79 | (WINAPI *SymInitializeW)( 80 | __in HANDLE hProcess, 81 | __in_opt PCWSTR UserSearchPath, 82 | __in BOOL fInvadeProcess 83 | ); 84 | 85 | DWORD 86 | (WINAPI *SymSetOptions)( 87 | __in DWORD SymOptions 88 | ); 89 | 90 | DWORD 91 | (WINAPI *SymGetOptions)( 92 | VOID 93 | ); 94 | 95 | BOOL 96 | (WINAPI *SymGetModuleInfoW64)( 97 | __in HANDLE hProcess, 98 | __in DWORD64 qwAddr, 99 | __out PIMAGEHLP_MODULEW64 ModuleInfo 100 | ); 101 | 102 | BOOL 103 | (WINAPI *SymFromAddrW)( 104 | __in HANDLE hProcess, 105 | __in DWORD64 Address, 106 | __out_opt PDWORD64 Displacement, 107 | __inout PSYMBOL_INFOW Symbol 108 | ); 109 | 110 | BOOL 111 | (WINAPI *SymGetLineFromAddrW64)( 112 | __in HANDLE hProcess, 113 | __in DWORD64 qwAddr, 114 | __out PDWORD pdwDisplacement, 115 | __out PIMAGEHLP_LINEW64 Line64 116 | ); 117 | 118 | BOOL 119 | (WINAPI *SymRegisterCallbackW64)( 120 | __in HANDLE hProcess, 121 | __in PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction, 122 | __in ULONG64 UserContext 123 | ); 124 | 125 | BOOL 126 | (WINAPI *SymRefreshModuleList)( 127 | __in HANDLE hProcess 128 | ); 129 | 130 | DWORD64 131 | (WINAPI *SymLoadModuleExW)( 132 | __in HANDLE hProcess, 133 | __in_opt HANDLE hFile, 134 | __in_opt PCTSTR ImageName, 135 | __in_opt PCTSTR ModuleName, 136 | __in DWORD64 BaseOfDll, 137 | __in DWORD DllSize, 138 | __in_opt PMODLOAD_DATA Data, 139 | __in_opt DWORD Flags 140 | ); 141 | 142 | void 143 | (WINAPI *SymSetDbgPrint)( 144 | void (*fn)(const char *str) 145 | ); 146 | 147 | BOOL 148 | (WINAPI *MiniDumpWriteDump)( 149 | __in HANDLE hProcess, 150 | __in DWORD ProcessId, 151 | __in HANDLE hFile, 152 | __in MINIDUMP_TYPE DumpType, 153 | __in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, 154 | __in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, 155 | __in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam 156 | ); 157 | 158 | LPCWSTR Name; 159 | bool Loaded; 160 | DbgHelp() : Loaded(false) {} 161 | }; 162 | 163 | extern DbgHelp dbgHelpMs; 164 | extern DbgHelp dbgHelpDrMingw; 165 | extern DbgHelp dbgHelpWine; 166 | extern DbgHelp dbgHelpWineWow64; 167 | 168 | bool dbgHelpInit(); 169 | 170 | #endif // __DBGINTERFACE_H__ 171 | -------------------------------------------------------------------------------- /src/utils/except.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | except.h 3 | ---------------- 4 | 5 | Copyright (C) 2015 Ashod Nakashian 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html.. 22 | =====================================================================*/ 23 | 24 | #pragma once 25 | 26 | #include 27 | #include 28 | 29 | class SleepyException : public std::runtime_error 30 | { 31 | std::wstring _what; 32 | 33 | std::string helper(const wchar_t *what) 34 | { 35 | // Need a temporary to build std::string. 36 | // Can't use _what in initialization-list because 37 | // it will always be initialized after the superclass. 38 | // Can't use _what here because it is still not initialized 39 | // and contains junk. 40 | std::wstring ws(what); 41 | return std::string(ws.begin(), ws.end()); 42 | } 43 | 44 | public: 45 | SleepyException(const std::string &what) 46 | : std::runtime_error(what), _what(std::wstring(what.begin(), what.end())) {} 47 | 48 | SleepyException(const std::wstring &what) 49 | : std::runtime_error(std::string(what.begin(), what.end())), _what(what) {} 50 | 51 | SleepyException(const wchar_t *what) 52 | : std::runtime_error(helper(what)), _what(what) {} 53 | 54 | const std::wstring &wwhat() const { return _what; } 55 | }; 56 | 57 | template 58 | static T enforce(T cond, const S &text) 59 | { 60 | if (cond) 61 | return cond; 62 | throw SleepyException(text); 63 | } 64 | 65 | #include 66 | #include 67 | 68 | template 69 | T wenforce(T cond, const S& where) 70 | { 71 | if (cond) 72 | return cond; 73 | 74 | DWORD code = GetLastError(); 75 | 76 | std::wostringstream message; 77 | message << where; 78 | 79 | if (code) 80 | { 81 | wchar_t *lpMsgBuf = NULL; 82 | FormatMessageW( 83 | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 84 | NULL, 85 | code, 86 | MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 87 | (LPWSTR)&lpMsgBuf, 88 | 0, 89 | NULL); 90 | 91 | if (lpMsgBuf) 92 | { 93 | message << ": " << lpMsgBuf; 94 | LocalFree(lpMsgBuf); 95 | } 96 | else 97 | message << " failed"; 98 | 99 | message << " (error " << code << ")"; 100 | } 101 | else 102 | message << " failed"; 103 | 104 | throw SleepyException(message.str()); 105 | } 106 | -------------------------------------------------------------------------------- /src/utils/mythread.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | MyThread.cpp 3 | ------------ 4 | 5 | Copyright (C) Nicholas Chapman 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #include "mythread.h" 24 | 25 | #include 26 | #include 27 | 28 | MyThread::~MyThread() 29 | { 30 | #ifndef NDEBUG 31 | DWORD dwExitCode; 32 | BOOL res = GetExitCodeThread(thread_handle, &dwExitCode); 33 | assert(res != 0 && dwExitCode != STILL_ACTIVE); 34 | #endif//NDEBUG 35 | CloseHandle(thread_handle); 36 | } 37 | 38 | HANDLE MyThread::launch(int priority_) 39 | { 40 | assert(thread_handle == NULL); 41 | 42 | thread_handle = (HANDLE)_beginthreadex(NULL, 0, threadFunction, this, 0, NULL); 43 | SetThreadPriority( thread_handle, priority_ ); 44 | 45 | return thread_handle; 46 | } 47 | 48 | 49 | unsigned __stdcall MyThread::threadFunction(void* the_thread_) 50 | { 51 | MyThread* the_thread = static_cast(the_thread_); 52 | 53 | assert(the_thread != NULL); 54 | 55 | the_thread->run(); 56 | 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /src/utils/mythread.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | MyThread.h 3 | ---------- 4 | 5 | Copyright (C) Nicholas Chapman 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #ifndef __MYTHREAD_H_666_ 24 | #define __MYTHREAD_H_666_ 25 | 26 | #include 27 | 28 | /*===================================================================== 29 | MyThread 30 | -------- 31 | Thanks to someone from the COTD on flipcode for the code this is based on 32 | =====================================================================*/ 33 | class MyThread 34 | { 35 | public: 36 | MyThread() : thread_handle(NULL) {} 37 | virtual ~MyThread(); 38 | 39 | virtual void run() = 0; 40 | HANDLE launch(int priority); 41 | bool launched() const { return !!thread_handle; } 42 | void waitFor(DWORD dwMilliseconds) { WaitForSingleObject(thread_handle, dwMilliseconds); } 43 | void join() { WaitForSingleObject(thread_handle, INFINITE); } 44 | void setPriority(int priority) { SetThreadPriority(thread_handle, priority); } 45 | 46 | private: 47 | static unsigned __stdcall threadFunction(void* the_thread); 48 | 49 | HANDLE thread_handle; 50 | }; 51 | 52 | #endif //__MYTHREAD_H_666_ 53 | -------------------------------------------------------------------------------- /src/utils/osutils.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | osutils.cpp 3 | ------------ 4 | 5 | Copyright (C) Dan Engelbrecht 6 | Copyright (C) 2015 Ashod Nakashian 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | 25 | #include "osutils.h" 26 | #include "WoW64.h" 27 | 28 | static bool is64BitOS = false; 29 | static bool is64BitProfiler = false; 30 | static int totalCpuCount = 1; 31 | 32 | typedef BOOL WINAPI IsWow64Process_t(__in HANDLE hProcess, __out PBOOL Wow64Process); 33 | static IsWow64Process_t *IsWow64ProcessPtr = NULL; 34 | 35 | void InitSysInfo() 36 | { 37 | SYSTEM_INFO systemInfo = { 0 }; 38 | GetNativeSystemInfo(&systemInfo); 39 | totalCpuCount = systemInfo.dwNumberOfProcessors; 40 | is64BitOS = (systemInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64); 41 | 42 | is64BitProfiler = (sizeof(void*) > 4); 43 | IsWow64ProcessPtr = (IsWow64Process_t *)GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process"); 44 | } 45 | 46 | int GetCPUCores() 47 | { 48 | return totalCpuCount; 49 | } 50 | 51 | int GetCountFromBitMask(DWORD bitMask){ 52 | int count = 0; 53 | while(bitMask != 0){ 54 | if((bitMask & 1) != 0){ 55 | ++count; 56 | } 57 | bitMask = bitMask >> 1; 58 | } 59 | return count; 60 | } 61 | 62 | int GetCoresForProcess(HANDLE process){ 63 | DWORD_PTR processAffinityMask = 0; 64 | DWORD_PTR systemAffinityMask = 0; 65 | BOOL okFlag = ::GetProcessAffinityMask(process, &processAffinityMask, &systemAffinityMask); 66 | if((okFlag == FALSE) || (processAffinityMask == 0)){ 67 | return GetCPUCores(); 68 | } 69 | else{ 70 | return GetCountFromBitMask(DWORD(processAffinityMask)); 71 | } 72 | } 73 | 74 | void EnableDebugPrivilege() 75 | { 76 | HANDLE hToken; 77 | LUID luid; 78 | TOKEN_PRIVILEGES tkp; 79 | 80 | OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ); 81 | 82 | LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid ); 83 | 84 | tkp.PrivilegeCount = 1; 85 | tkp.Privileges[0].Luid = luid; 86 | tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 87 | 88 | AdjustTokenPrivileges( hToken, false, &tkp, sizeof( tkp ), NULL, NULL ); 89 | 90 | CloseHandle( hToken ); 91 | } 92 | 93 | /* 94 | Bitness possibility matrix. 95 | 96 | Profiler | Profilee | OS 97 | ----------------------------- 98 | 32-bits | 32-bits | 32-bits (Native) 99 | 32-bits | 32-bits | WOW64 100 | 32-bits | 64-bits | 64-bits (Unsupported) 101 | 102 | 64-bits | 32-bits | WOW64 103 | 64-bits | 64-bits | 64-bits (Native) 104 | */ 105 | 106 | bool CanProfileProcess(HANDLE hProcess) 107 | { 108 | if (Is64BitProcess(hProcess)) 109 | { 110 | // 64-bit with a 64-bit profiler only. 111 | return is64BitProfiler; 112 | } 113 | 114 | //TODO: Check security permissions? 115 | 116 | #ifdef _WIN64 117 | if (fn_Wow64SuspendThread == NULL || fn_Wow64GetThreadContext == NULL) 118 | { 119 | // Skip 32 bit processes on system that does not have the needed functions (Windows XP 64). 120 | return false; 121 | } 122 | #endif 123 | 124 | // Any 32-bit profilee is supported. 125 | return true; 126 | } 127 | 128 | bool Is64BitProcess(HANDLE hProcess) 129 | { 130 | // If the process is running under 32-bit Windows, the value is set to FALSE. 131 | // If the process is a 64-bit application running under 64-bit Windows, the value is also set to FALSE. 132 | // Meaning, this is TRUE if, and only if, the process is 32-bits running under 64-bit Windows. 133 | BOOL isWow64Process; 134 | 135 | return (is64BitOS && 136 | IsWow64ProcessPtr && 137 | IsWow64ProcessPtr(hProcess, &isWow64Process) && 138 | !isWow64Process); 139 | } 140 | -------------------------------------------------------------------------------- /src/utils/osutils.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | osutils.h 3 | ---------- 4 | 5 | Copyright (C) Dan Engelbrecht 6 | Copyright (C) 2015 Ashod Nakashian 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | 25 | #pragma once 26 | #ifndef __OSUTILS_H__ 27 | #define __OSUTILS_H__ 28 | 29 | #include 30 | 31 | void InitSysInfo(); 32 | int GetCPUCores(); 33 | int GetCoresForProcess(HANDLE process); 34 | void EnableDebugPrivilege(); 35 | bool Is64BitProcess(HANDLE hProcess); 36 | 37 | bool CanProfileProcess(HANDLE hProcess); 38 | 39 | #endif // __OSUTILS_H__ 40 | -------------------------------------------------------------------------------- /src/utils/sortlist.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | sortlist.cpp 3 | ------------ 4 | 5 | Copyright (C) Richard Mitton 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #include "sortlist.h" 24 | #include 25 | 26 | /* XPM */ 27 | static char *sort_none_xpm[] = { 28 | /* columns rows colors chars-per-pixel */ 29 | "16 16 2 1", 30 | ". c #ACA899", 31 | " c #FF0000", 32 | /* pixels */ 33 | " ", 34 | " ", 35 | " ", 36 | " ", 37 | " ", 38 | " ", 39 | " ", 40 | " ", 41 | " ", 42 | " ", 43 | " ", 44 | " ", 45 | " ", 46 | " ", 47 | " ", 48 | " " 49 | }; 50 | 51 | /* XPM */ 52 | static char *sort_up_xpm[] = { 53 | /* columns rows colors chars-per-pixel */ 54 | "16 16 2 1", 55 | ". c #ACA899", 56 | " c #FF0000", 57 | /* pixels */ 58 | " ", 59 | " ", 60 | " ", 61 | " ", 62 | " ", 63 | " ", 64 | " . ", 65 | " ... ", 66 | " ..... ", 67 | " ....... ", 68 | " ......... ", 69 | " ", 70 | " ", 71 | " ", 72 | " ", 73 | " " 74 | }; 75 | 76 | /* XPM */ 77 | static char *sort_down_xpm[] = { 78 | /* columns rows colors chars-per-pixel */ 79 | "16 16 2 1", 80 | ". c #ACA899", 81 | " c #FF0000", 82 | /* pixels */ 83 | " ", 84 | " ", 85 | " ", 86 | " ", 87 | " ", 88 | " ", 89 | " ......... ", 90 | " ....... ", 91 | " ..... ", 92 | " ... ", 93 | " . ", 94 | " ", 95 | " ", 96 | " ", 97 | " ", 98 | " " 99 | }; 100 | 101 | void wxSortedListCtrl::InitSort() 102 | { 103 | wxImageList *images = new wxImageList; 104 | wxImage sort_none_img(sort_none_xpm); 105 | wxSize size = FromDIP(sort_none_img.GetSize()); 106 | images->Create(size.x, size.y, true, 3); 107 | images->Add(sort_none_img.Rescale(size.x, size.y), wxColor(255,0,0)); 108 | images->Add(wxImage(sort_up_xpm).Rescale(size.x, size.y), wxColor(255,0,0)); 109 | images->Add(wxImage(sort_down_xpm).Rescale(size.x, size.y), wxColor(255,0,0)); 110 | AssignImageList(images, wxIMAGE_LIST_SMALL); 111 | } 112 | 113 | void wxSortedListCtrl::SetSortImage(int col, SortType type) 114 | { 115 | wxListItem item; 116 | item.SetMask(wxLIST_MASK_IMAGE); 117 | item.SetImage(type); 118 | SetColumn(col, item); 119 | } 120 | -------------------------------------------------------------------------------- /src/utils/sortlist.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | sortlist.h 3 | ---------- 4 | 5 | Copyright (C) Richard Mitton 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #ifndef __SORTLIST_H_666_ 24 | #define __SORTLIST_H_666_ 25 | 26 | #include 27 | 28 | class wxSortedListCtrl : public wxListCtrl 29 | { 30 | public: 31 | wxSortedListCtrl() { Init(); } 32 | 33 | wxSortedListCtrl(wxWindow *parent, 34 | wxWindowID id = wxID_ANY, 35 | const wxPoint& pos = wxDefaultPosition, 36 | const wxSize& size = wxDefaultSize, 37 | long style = wxLC_ICON, 38 | const wxValidator& validator = wxDefaultValidator, 39 | const wxString& name = wxListCtrlNameStr) 40 | { 41 | Init(); 42 | 43 | Create(parent, id, pos, size, style, validator, name); 44 | } 45 | 46 | enum SortType { SORT_NONE, SORT_UP, SORT_DOWN }; 47 | 48 | void InitSort(); 49 | void SetSortImage(int col, SortType type); 50 | }; 51 | 52 | #endif // __SORTLIST_H_666_ 53 | -------------------------------------------------------------------------------- /src/utils/stringutils.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | stringutils.cpp 3 | --------------- 4 | 5 | Copyright (C) Nicholas Chapman 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #ifndef __STRINGUTILS_H__ 24 | #define __STRINGUTILS_H__ 25 | 26 | 27 | //NOTE: not all of this code has been used/tested for ages. 28 | //Your mileage may vary; test the code before you use it!!!! 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | 36 | inline float stringToFloat(const std::wstring& s) 37 | { 38 | return (float)_wtof(s.c_str()); 39 | } 40 | 41 | inline int stringToInt(const std::wstring& s) 42 | { 43 | return _wtoi(s.c_str()); 44 | } 45 | 46 | inline double stringToDouble(const std::wstring& s) 47 | { 48 | return _wtof(s.c_str()); 49 | } 50 | 51 | 52 | unsigned int hexStringToUInt(const std::wstring& s); 53 | unsigned long long hexStringTo64UInt(const std::wstring& s); 54 | 55 | //const std::wstring toHexString(unsigned int i);//32 bit integers 56 | const std::wstring toHexString(unsigned long long i);//for 64 bit integers 57 | const std::wstring intToString(int i); 58 | const std::wstring floatToString(float f); 59 | const std::wstring doubleToString(double d); 60 | const std::wstring floatToString(float f, int num_decimal_places); 61 | 62 | 63 | 64 | //argument overloaded toString functions: 65 | inline const std::wstring toString(double f) 66 | { 67 | return doubleToString(f); 68 | } 69 | 70 | inline const std::wstring toString(float f) 71 | { 72 | return floatToString(f); 73 | } 74 | 75 | inline const std::wstring toString(int i) 76 | { 77 | return intToString(i); 78 | } 79 | 80 | inline const std::wstring toString(char c) 81 | { 82 | return std::wstring(1, c); 83 | } 84 | 85 | 86 | 87 | 88 | 89 | __forceinline bool isWhitespace(char c) 90 | { 91 | return c == ' ' || c == '\t' || c == '\n' || c == '\r'; 92 | } 93 | 94 | __forceinline bool isAlpha(char c) 95 | { 96 | return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); 97 | } 98 | 99 | __forceinline bool isCToken(char c) 100 | { 101 | return isAlpha(c) || c == '_' || c == '#'; 102 | } 103 | 104 | void readQuote(std::wistream& stream, std::wstring& str_out);//reads string from between double quotes. 105 | 106 | template 107 | void writeQuote(T& stream, const std::wstring& s, wchar_t escape = '\\') 108 | { 109 | stream << '"'; 110 | for (size_t i = 0; i < s.length(); i++) 111 | { 112 | wchar_t c = s[i]; 113 | if (c == escape || c == '"') 114 | stream << escape; 115 | stream << c; 116 | } 117 | stream << '"'; 118 | } 119 | 120 | struct StringSet 121 | { 122 | std::vector strings; 123 | bool caseCheck; 124 | public: 125 | StringSet(const wchar_t *file, bool caseCheck); 126 | void Add(const wchar_t *string); 127 | void Remove(const wchar_t *string); 128 | bool Contains(const wchar_t *string) const; 129 | }; 130 | 131 | 132 | struct StringList 133 | { 134 | std::wstring string; 135 | public: 136 | StringList(const wchar_t *file); 137 | void Add(const wchar_t *str); 138 | const std::wstring& Get() const { return string; } 139 | }; 140 | 141 | #endif //__STRINGUTILS_H__ 142 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/CallstackView.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | proclist.h 3 | ---------- 4 | File created by ClassTemplate on Tue Mar 15 21:13:18 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | 25 | class CallstackView; 26 | 27 | #include "profilergui.h" 28 | #include "database.h" 29 | 30 | #ifndef __CALLSTTACKVIEW_H_ 31 | #define __CALLSTTACKVIEW_H_ 32 | 33 | class wxStaticTextTransparent; 34 | 35 | class CallstackView : public wxWindow 36 | { 37 | wxAuiToolBar *toolBar; 38 | wxListCtrl *listCtrl; 39 | wxStaticTextTransparent *toolRange; 40 | Database *database; 41 | 42 | enum ColumnType 43 | { 44 | COL_NAME, 45 | COL_MODULE, 46 | COL_SOURCEFILE, 47 | COL_SOURCELINE, 48 | COL_ADDRESS, 49 | MAX_COLUMNS 50 | }; 51 | 52 | enum ToolId 53 | { 54 | TOOL_PREV, 55 | TOOL_NEXT, 56 | TOOL_EXPORT_CSV, 57 | }; 58 | 59 | enum ListCtrl { 60 | LIST_CTRL = 1000 61 | }; 62 | 63 | std::vector callstacks; 64 | size_t callstackActive; 65 | wxString callstackStats; 66 | const Database::Symbol *currSymbol; 67 | size_t itemSelected; 68 | 69 | void setupColumn(ColumnType id, int width, const wxString &name); 70 | void updateList(); 71 | void updateTools(); 72 | void exportCSV(wxFileOutputStream &file); 73 | 74 | public: 75 | CallstackView(wxWindow *parent, Database *database); 76 | virtual ~CallstackView(void); 77 | void OnSize(wxSizeEvent& event); 78 | void OnTool(wxCommandEvent &event); 79 | void OnSelected(wxListEvent& event); 80 | void OnContextMenu(wxContextMenuEvent& event); 81 | public: 82 | void showCallStack(const Database::Symbol *symbol); 83 | void reset(); 84 | DECLARE_EVENT_TABLE() 85 | 86 | }; 87 | 88 | #endif 89 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/aboutdlg.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | aboutdlg.cpp 3 | ------------- 4 | File created by ClassTemplate on Sun Mar 13 18:16:34 2005 5 | 6 | Copyright (C) Vladimir Panteleev 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | 25 | #include "aboutdlg.h" 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "../appinfo.h" 31 | #include "../version.h" 32 | 33 | AboutDlg::AboutDlg() 34 | { 35 | Init(); 36 | 37 | if ( !wxDialog::Create(NULL, wxID_ANY, _T("About ") _T(APPNAME), 38 | wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE) ) 39 | return; 40 | 41 | m_sizerText = new wxBoxSizer(wxVERTICAL); 42 | 43 | wxString nameAndVersion = _T(APPNAME) _T(" ") _T(VERSION); 44 | wxSizer *sizerIconAndTitle = new wxBoxSizer(wxHORIZONTAL); 45 | wxIcon icon = wxAboutDialogInfo().GetIcon(); 46 | if ( icon.Ok() ) 47 | sizerIconAndTitle->Add(new wxStaticBitmap(this, wxID_ANY, icon), 0, wxRIGHT, FromDIP(20)); 48 | 49 | wxSizer *sizerTitle = new wxBoxSizer(wxVERTICAL); 50 | { 51 | wxStaticText *label = new wxStaticText(this, wxID_ANY, nameAndVersion); 52 | wxFont font(*wxNORMAL_FONT); 53 | font.SetPointSize(font.GetPointSize() + FromDIP(3)); 54 | font.SetWeight(wxFONTWEIGHT_BOLD); 55 | label->SetFont(font); 56 | 57 | sizerTitle->Add(label, 0, wxBOTTOM, FromDIP(4)); 58 | } 59 | { 60 | wxStaticText *label = new wxStaticText(this, wxID_ANY, _T("Open-source CPU profiler")); 61 | label->SetFont(*wxITALIC_FONT); 62 | 63 | sizerTitle->Add(label, 0, wxBOTTOM, FromDIP(4)); 64 | } 65 | sizerTitle->Add(new wxStaticLine(this), wxSizerFlags().Expand()); 66 | 67 | sizerIconAndTitle->Add(sizerTitle, 1, wxEXPAND); 68 | 69 | m_sizerText->Add(sizerIconAndTitle, 1, wxEXPAND); 70 | m_sizerText->AddSpacer(FromDIP(10)); 71 | 72 | // AddText(_T(APPNAME) L":"); 73 | // AddDev("Your Name Here", "http://example.com/", "maintainer"); 74 | 75 | AddText("Very Sleepy:"); 76 | AddDev("Richard Mitton", "http://www.codersnotes.com/", "maintainer"); 77 | AddDev("Vladimir Panteleev", "http://thecybershadow.net/", "maintainer"); 78 | AddDev("Richard Munn", "https://github.com/benjymous", "time limit, filters, highlights"); 79 | AddDev("Michael Vance", "", "callstack CSV export"); 80 | AddDev(L"Bernat Mu\x00F1oz Garcia", "https://github.com/shashClp", "Scintilla syntax highlighting"); 81 | AddDev("Dan Engelbrecht", "", "threading"); 82 | AddDev(L"Johan K" L"\x00F6" L"hler", "", "64-bit"); 83 | AddDev("... and many other kind people contributing patches.", "", ""); 84 | 85 | AddText("Sleepy:"); 86 | AddDev("Nicholas Chapman", "http://sleepy.sourceforge.net/", "creator"); 87 | 88 | AddControl(new wxStaticLine(this), wxSizerFlags().Expand()); 89 | AddText(L"Copyright \x00A9 authors and contributors.\n" 90 | L"\n" 91 | L"This program is released under the GNU Public License.\n" 92 | L"See LICENSE.TXT for more information."); 93 | 94 | AddControl(new wxStaticLine(this), wxSizerFlags().Expand()); 95 | wxHyperlinkCtrl *link = new wxHyperlinkCtrl(this, wxID_ANY, 96 | _T(APPNAME) _T(" web site"), 97 | _T(APPURL)); 98 | link->SetToolTip(_T(APPURL)); 99 | AddControl(link, wxSizerFlags().Center()); 100 | 101 | wxSizer *sizerBtns = CreateButtonSizer(wxOK); 102 | if ( sizerBtns ) 103 | { 104 | m_sizerText->Add(sizerBtns, wxSizerFlags().Expand().Border()); 105 | } 106 | 107 | wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL); 108 | sizerTop->Add(m_sizerText, 1, wxEXPAND|wxALL, FromDIP(10)); 109 | SetSizerAndFit(sizerTop); 110 | 111 | CentreOnScreen(); 112 | } 113 | 114 | void AboutDlg::AddControl(wxWindow *win, const wxSizerFlags& flags) 115 | { 116 | wxSizerFlags newflags = flags; 117 | m_sizerText->Add(win, newflags.Border(wxTOP|wxBOTTOM)); 118 | } 119 | 120 | void AboutDlg::AddControl(wxWindow *win) 121 | { 122 | AddControl(win, wxSizerFlags()); 123 | } 124 | 125 | void AboutDlg::AddText(const wxString& text) 126 | { 127 | if (!text.empty()) 128 | AddControl(new wxStaticText(this, wxID_ANY, text)); 129 | } 130 | 131 | void AboutDlg::AddDev(const wxString& name, const wxString& url, const wxString &role) 132 | { 133 | wxSizer *s = new wxBoxSizer(wxHORIZONTAL); 134 | s->Add(new wxStaticText(this, wxID_ANY, L" \x00BB ")); 135 | if (url.empty()) 136 | s->Add(new wxStaticText(this, wxID_ANY, name)); 137 | else 138 | { 139 | wxHyperlinkCtrl* link = new wxHyperlinkCtrl(this, wxID_ANY, name, url); 140 | link->SetToolTip(url); 141 | s->Add(link); 142 | } 143 | if (!role.empty()) 144 | s->Add(new wxStaticText(this, wxID_ANY, L" (" + role + ")")); 145 | m_sizerText->Add(s); 146 | } 147 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/aboutdlg.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | aboutdlg.h 3 | ------------- 4 | File created by ClassTemplate on Sun Mar 13 18:16:34 2005 5 | 6 | Copyright (C) Vladimir Panteleev 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | // ---------------------------------------------------------------------------- 30 | // AboutDlg 31 | // Less-rubbish about dialog 32 | // ---------------------------------------------------------------------------- 33 | class AboutDlg : public wxDialog 34 | { 35 | public: 36 | AboutDlg(); 37 | 38 | private: 39 | void AddControl(wxWindow *win, const wxSizerFlags& flags); 40 | void AddControl(wxWindow *win); 41 | void AddText(const wxString& text); 42 | void AddDev(const wxString& name, const wxString& url, const wxString &role); 43 | 44 | wxSizer *m_sizerText; 45 | }; 46 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/capturewin.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | capturewin.h 3 | -------------- 4 | 5 | Copyright (C) Richard Mitton 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #ifndef __CAPTUREWIN_H__ 24 | #define __CAPTUREWIN_H__ 25 | 26 | #include "profilergui.h" 27 | 28 | class CaptureWin : public wxDialog 29 | { 30 | public: 31 | CaptureWin(); 32 | virtual ~CaptureWin(); 33 | 34 | bool UpdateProgress(const wchar_t *status, double progress); 35 | 36 | bool Paused() { return paused; } 37 | bool Cancelled() { return cancelled; } 38 | 39 | virtual WXLRESULT MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam); 40 | 41 | private: 42 | void OnOk( wxCommandEvent & event ); 43 | void OnPause( wxCommandEvent & event ); 44 | void OnCancel( wxCommandEvent & event ); 45 | 46 | bool cancelled, stopped, paused; 47 | wxGauge *progressBar; 48 | wxStaticText *progressText; 49 | class wxBitmapToggleButton *pauseButton; 50 | struct ITaskbarList3 *win7taskBar; 51 | 52 | DECLARE_EVENT_TABLE() 53 | }; 54 | 55 | 56 | #endif //__CAPTUREWIN_H__ 57 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/contextmenu.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | launchdlg.cpp 3 | ---------------- 4 | 5 | Copyright (C) Johan Kohler 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | 24 | #include "CallstackView.h" 25 | #include "contextmenu.h" 26 | #include "mainwin.h" 27 | #include 28 | #include 29 | #include 30 | 31 | enum { 32 | ID_COLLAPSE_FUNC=2001, 33 | ID_COLLAPSE_MOD, 34 | ID_SET_ROOT, 35 | ID_FILTER_FUNC, 36 | ID_FILTER_MODULE, 37 | ID_FILTER_SOURCE, 38 | ID_HIGHLIGHT, 39 | ID_UNHIGHLIGHT, 40 | ID_COPY, 41 | }; 42 | 43 | class FunctionMenuWindow : public wxWindow 44 | { 45 | public: 46 | int option; 47 | 48 | FunctionMenuWindow(wxWindow *parent) : wxWindow(parent, -1), option(0), mPushed(false) 49 | { 50 | this ->Bind(wxEVT_MENU , &FunctionMenuWindow::OnMenu , this, wxID_ANY); 51 | theMainWin->Bind(wxEVT_MENU_OPEN , &FunctionMenuWindow::OnOpen , this, wxID_ANY); 52 | theMainWin->Bind(wxEVT_MENU_CLOSE , &FunctionMenuWindow::OnClose , this, wxID_ANY); 53 | theMainWin->Bind(wxEVT_MENU_HIGHLIGHT, &FunctionMenuWindow::OnHighlight, this, wxID_ANY); 54 | } 55 | 56 | ~FunctionMenuWindow() 57 | { 58 | theMainWin->Unbind(wxEVT_MENU_OPEN , &FunctionMenuWindow::OnOpen , this, wxID_ANY); 59 | theMainWin->Unbind(wxEVT_MENU_CLOSE , &FunctionMenuWindow::OnClose , this, wxID_ANY); 60 | theMainWin->Unbind(wxEVT_MENU_HIGHLIGHT, &FunctionMenuWindow::OnHighlight, this, wxID_ANY); 61 | } 62 | 63 | private: 64 | void OnMenu(wxCommandEvent& event) 65 | { 66 | option = event.GetId(); 67 | } 68 | 69 | void OnOpen(wxMenuEvent &event) 70 | { 71 | this->mMenu = event.GetMenu(); 72 | if (!mPushed) 73 | { 74 | theMainWin->GetStatusBar()->PushStatusText(wxString()); 75 | mPushed = true; 76 | } 77 | } 78 | 79 | void OnClose(wxMenuEvent &WXUNUSED(event)) 80 | { 81 | if (mPushed) 82 | { 83 | theMainWin->GetStatusBar()->PopStatusText(); 84 | mPushed = false; 85 | } 86 | } 87 | 88 | const wxString GetHelpString(wxMenuEvent &event) 89 | { 90 | if (event.GetMenuId() < 0) 91 | return wxString(); 92 | else 93 | return mMenu->GetHelpString(event.GetMenuId()); 94 | } 95 | 96 | void OnHighlight(wxMenuEvent &event) 97 | { 98 | if (mPushed) 99 | theMainWin->GetStatusBar()->SetStatusText(GetHelpString(event)); 100 | else 101 | { 102 | theMainWin->GetStatusBar()->PushStatusText(GetHelpString(event)); 103 | mPushed = true; 104 | } 105 | } 106 | 107 | bool mPushed; 108 | wxMenu* mMenu; 109 | }; 110 | 111 | void FunctionMenu(wxListCtrl *list, Database *database) 112 | { 113 | FunctionMenuWindow funcWindow(list); 114 | wxMenu *menu = new wxMenu; 115 | 116 | Database::Address addr; 117 | const Database::Symbol* sym; 118 | std::vector selection; 119 | 120 | { 121 | long i = list->GetNextItem(-1, wxLIST_NEXT_ALL, wxLIST_STATE_FOCUSED); 122 | if (i < 0) 123 | return; 124 | const Database::AddrInfo *addrinfo = (const Database::AddrInfo *)list->GetItemData(i); 125 | sym = addrinfo->symbol; 126 | addr = sym->address; 127 | } 128 | 129 | for (long item = -1;;) 130 | { 131 | item = list->GetNextItem(item, 132 | wxLIST_NEXT_ALL, 133 | wxLIST_STATE_SELECTED); 134 | if (item == -1) 135 | break; 136 | 137 | const Database::AddrInfo *itemaddrinfo = (const Database::AddrInfo *)list->GetItemData(item); 138 | selection.push_back(itemaddrinfo->symbol->address); 139 | } 140 | 141 | if (selection.size() == 0) 142 | return; 143 | 144 | // Focused symbol properties 145 | wxString procname = sym->procname; 146 | wxString sourcefilename = database->getFileName (sym->sourcefile); 147 | wxString modulename = database->getModuleName(sym->module ); 148 | 149 | menu->Append(ID_COPY, "&Copy"); 150 | menu->AppendSeparator(); 151 | 152 | if (selection.size() == 1) 153 | { 154 | wxString modUpper = modulename; 155 | modUpper.UpperCase(); 156 | 157 | menu->AppendCheckItem(ID_COLLAPSE_FUNC, 158 | "Collapse child calls", 159 | "Present all CPU time in functions called by this function as if inside this function") 160 | ->Check(IsOsFunction(procname)); 161 | menu->AppendCheckItem(ID_COLLAPSE_MOD, 162 | wxString::Format("Collapse all %s calls", modUpper), 163 | "Present all CPU time in functions called by functions in this module as if inside functions in this module") 164 | ->Check(IsOsModule(modUpper)); 165 | menu->AppendCheckItem(ID_SET_ROOT, 166 | wxString::Format("Set root to %s", procname), 167 | "Ignore all CPU samples except for functions called by this function"); 168 | 169 | menu->AppendSeparator(); 170 | 171 | menu->AppendCheckItem(ID_FILTER_FUNC, 172 | wxString::Format("Filter functions to %s", procname), 173 | "Ignore all CPU samples except inside this function"); 174 | menu->AppendCheckItem(ID_FILTER_MODULE, 175 | wxString::Format("Filter modules to %s", modulename), 176 | "Ignore all CPU samples except inside this module"); 177 | menu->AppendCheckItem(ID_FILTER_SOURCE, 178 | wxString::Format("Filter source files to %s", sourcefilename), 179 | "Ignore all CPU samples except inside this source file"); 180 | menu->AppendSeparator(); 181 | } 182 | 183 | wxString highlightTarget = selection.size()==1 ? sym->procname : L"selected"; 184 | if (set_get(theMainWin->getViewState()->highlighted, addr)) 185 | menu->AppendCheckItem(ID_UNHIGHLIGHT, wxString::Format("Unhighlight %s", highlightTarget)); 186 | else 187 | menu->AppendCheckItem(ID_HIGHLIGHT , wxString::Format("Highlight %s" , highlightTarget)); 188 | 189 | funcWindow.PopupMenu(menu); 190 | switch(funcWindow.option) 191 | { 192 | case ID_COPY: 193 | { 194 | std::wstringstream buf; 195 | for (long item = -1;;) 196 | { 197 | item = list->GetNextItem(item, 198 | wxLIST_NEXT_ALL, 199 | wxLIST_STATE_SELECTED); 200 | if (item == -1) 201 | break; 202 | 203 | for (int col = 0; col < list->GetColumnCount(); col++) 204 | { 205 | if (col) 206 | buf << '\t'; 207 | buf << list->GetItemText(item, col); 208 | } 209 | buf << '\n'; 210 | } 211 | wxTheClipboard->SetData(new wxTextDataObject(buf.str())); 212 | 213 | break; 214 | } 215 | 216 | case ID_COLLAPSE_FUNC: 217 | if (IsOsFunction(procname)) 218 | RemoveOsFunction(procname); 219 | else 220 | AddOsFunction(procname); 221 | theMainWin->refresh(); 222 | break; 223 | 224 | case ID_COLLAPSE_MOD: 225 | if (IsOsModule(modulename)) 226 | RemoveOsModule(modulename); 227 | else 228 | AddOsModule(modulename); 229 | theMainWin->refresh(); 230 | break; 231 | 232 | case ID_SET_ROOT: 233 | database->setRoot(sym); 234 | theMainWin->refresh(); 235 | break; 236 | 237 | case ID_FILTER_FUNC: 238 | theMainWin->setFilter("procname", procname); 239 | break; 240 | 241 | case ID_FILTER_MODULE: 242 | theMainWin->setFilter("module", modulename); 243 | break; 244 | 245 | case ID_FILTER_SOURCE: 246 | theMainWin->setFilter("sourcefile", sourcefilename); 247 | break; 248 | 249 | case ID_HIGHLIGHT: 250 | theMainWin->setHighlight(selection, true); 251 | break; 252 | case ID_UNHIGHLIGHT: 253 | theMainWin->setHighlight(selection, false); 254 | break; 255 | } 256 | } 257 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/contextmenu.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONTEXT_MENU_H_ 2 | #define _CONTEXT_MENU_H_ 3 | 4 | #include "database.h" 5 | #include "proclist.h" 6 | 7 | /// Show a right-click menu for a given wxListCtrl. 8 | /// We assume that the selected items are the actionable ones, 9 | /// and that the list stores Database::Address-es in its 10 | /// ItemData. 11 | void FunctionMenu(wxListCtrl *list, Database *database); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/database.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | database.h 3 | ---------- 4 | 5 | Copyright (C) Nicholas Chapman 6 | Copyright (C) Richard Mitton 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | #ifndef __DATABASE_H_666_ 25 | #define __DATABASE_H_666_ 26 | 27 | #include "profilergui.h" 28 | #include "../utils/container.h" 29 | 30 | bool IsOsFunction(wxString proc); 31 | void AddOsFunction(wxString proc); 32 | void RemoveOsFunction(wxString proc); 33 | 34 | bool IsOsModule(wxString mod); 35 | void AddOsModule(wxString mod); 36 | void RemoveOsModule(wxString mod); 37 | 38 | /*===================================================================== 39 | Database 40 | -------- 41 | 42 | =====================================================================*/ 43 | class Database 44 | { 45 | public: 46 | typedef unsigned long long Address; 47 | typedef size_t FileID; 48 | typedef size_t ModuleID; 49 | typedef unsigned ThreadID; 50 | 51 | /// Represents one function (as it appears in function lists). 52 | struct Symbol 53 | { 54 | /// Note: IDs may not persist across DB reloads 55 | /// (e.g. due to changes in symbol load settings). 56 | /// Use addresses to persistently refer to symbols in the GUI. 57 | typedef size_t ID; 58 | ID id; 59 | 60 | /// Points to the address of the start of the symbol 61 | /// (or the closest thing we have to that). 62 | /// Multiple addresses may belong to the same symbol. 63 | Address address; 64 | 65 | std::wstring procname; 66 | FileID sourcefile; 67 | ModuleID module; 68 | 69 | bool isCollapseFunction; 70 | bool isCollapseModule; 71 | }; 72 | 73 | /// Represents one address we encountered during profiling 74 | struct AddrInfo 75 | { 76 | AddrInfo() : symbol(NULL), sourceline(0) {} 77 | 78 | // Symbol info 79 | const Symbol *symbol; 80 | unsigned sourceline; 81 | 82 | // Per thread IP counts 83 | std::map samples; 84 | }; 85 | 86 | struct Item 87 | { 88 | const Symbol *symbol; 89 | 90 | /// Might be different from symbol->address 91 | /// (e.g. it's the call site for callstacks). 92 | Address address; 93 | 94 | double inclusive, exclusive; 95 | }; 96 | 97 | struct List 98 | { 99 | List() { totalcount = 0; } 100 | 101 | std::vector items; 102 | double totalcount; 103 | }; 104 | 105 | struct SymbolSamples 106 | { 107 | Symbol const *symbol; 108 | std::map exclusive, inclusive; 109 | double totalcount; 110 | }; 111 | 112 | struct CallStack 113 | { 114 | std::vector
addresses; 115 | 116 | // symbols[i] == addrsymbols[addresses[i]]. For convenience/performance. 117 | std::vector symbols; 118 | 119 | std::map samples; 120 | }; 121 | 122 | Database(); 123 | virtual ~Database(); 124 | void clear(); 125 | 126 | void loadFromPath(const std::wstring& profilepath,bool collapseOSCalls,bool loadMinidump); 127 | void reload(bool collapseOSCalls, bool loadMinidump); 128 | 129 | const Symbol *getSymbol(Symbol::ID id) const { return symbols[id]; } 130 | Symbol::ID getSymbolCount() const { return symbols.size(); } 131 | const std::wstring &getFileName(FileID id) const { return files[id]; } 132 | FileID getFileCount() const { return files.size(); } 133 | const std::wstring &getModuleName(ModuleID id) const { return modules[id]; } 134 | ModuleID getModuleCount() const { return modules.size(); } 135 | 136 | const AddrInfo *getAddrInfo(Address addr) { return &addrinfo.at(addr); } 137 | 138 | void setRoot(const Symbol *root); 139 | const Symbol *getRoot() const { return currentRoot; } 140 | 141 | const List &getMainList() const { return mainList; } 142 | List getCallers(const Symbol *symbol) const; 143 | List getCallees(const Symbol *symbol) const; 144 | SymbolSamples getSymbolSamples(const Symbol *symbol) const; 145 | std::vector getCallstacksContaining(const Symbol *symbol) const; 146 | std::vector getLineCounts(FileID sourcefile); 147 | 148 | std::vector stats; 149 | 150 | std::wstring getProfilePath() const { return profilepath; } 151 | 152 | bool has_minidump; 153 | 154 | double getFilteredSampleCount(std::map const &samples) const; 155 | 156 | std::unordered_map const &getThreadNames() const { return threadNames; } 157 | 158 | std::vector const &getFilterThreads() { return filterThreads; } 159 | void setFilterThreads(std::vector const &threads); 160 | 161 | private: 162 | /// Symbol::ID -> Symbol* 163 | std::vector symbols; 164 | 165 | /// filename <-> FileID 166 | std::vector files; 167 | std::unordered_map filemap; 168 | 169 | /// module name <-> ModuleID 170 | std::vector modules; 171 | std::unordered_map modulemap; 172 | 173 | /// Address -> module/procname/sourcefile/sourceline 174 | std::unordered_map addrinfo; 175 | 176 | std::unordered_map threadNames; 177 | 178 | std::vector callstacks; 179 | List mainList; 180 | std::wstring profilepath; 181 | const Symbol *currentRoot; 182 | std::vector filterThreads; 183 | 184 | void loadSymbols(wxInputStream &file); 185 | void loadCallstacks(wxInputStream &file,bool collapseKernelCalls); 186 | void loadThreads(wxInputStream &file); 187 | void loadStats(wxInputStream &file); 188 | void loadMinidump(wxInputStream &file); 189 | void scanMainList(); 190 | 191 | bool includeCallstack(const CallStack &callstack) const; 192 | 193 | // Any additional symbols we can load after opening a capture 194 | class LateSymbolInfo *late_sym_info; 195 | }; 196 | 197 | #endif //__DATABASE_H_666_ 198 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/latesymbolinfo.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | latesymbolinfo.cpp 3 | -------------- 4 | Copyright (C) Vladimir Panteleev 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | http://www.gnu.org/copyleft/gpl.html.. 21 | =====================================================================*/ 22 | 23 | #include "latesymbolinfo.h" 24 | #include 25 | #include "../utils/dbginterface.h" 26 | #include 27 | #include 28 | #include "../utils/except.h" 29 | 30 | #include "profilergui.h" 31 | 32 | void comenforce(HRESULT result, const char* where = NULL) 33 | { 34 | if (result == S_OK) 35 | return; 36 | 37 | std::wostringstream message; 38 | if (where) 39 | message << where; 40 | 41 | _com_error error(result); 42 | message << ": " << error.ErrorMessage(); 43 | message << " (error " << result << ")"; 44 | 45 | throw SleepyException(message.str()); 46 | } 47 | 48 | 49 | LateSymbolInfo::LateSymbolInfo() 50 | : debugClient5(NULL), debugControl4(NULL), debugSymbols3(NULL) 51 | { 52 | } 53 | 54 | LateSymbolInfo::~LateSymbolInfo() 55 | { 56 | unloadMinidump(); 57 | } 58 | 59 | // Send debugger output to the wxWidgets current logging facility. 60 | // The UI implements a logging facility in the form of a log panel. 61 | struct DebugOutputCallbacksWide : public IDebugOutputCallbacksWide 62 | { 63 | HRESULT STDMETHODCALLTYPE QueryInterface(__in REFIID WXUNUSED(InterfaceId), __out PVOID* WXUNUSED(Interface)) { return E_NOINTERFACE; } 64 | ULONG STDMETHODCALLTYPE AddRef() { return 1; } 65 | ULONG STDMETHODCALLTYPE Release() { return 0; } 66 | 67 | HRESULT STDMETHODCALLTYPE Output(__in ULONG WXUNUSED(Mask), __in PCWSTR Text) 68 | { 69 | //OutputDebugStringW(Text); 70 | wxLogMessage(L"%s", Text); 71 | return S_OK; 72 | } 73 | }; 74 | 75 | static DebugOutputCallbacksWide *debugOutputCallbacks = new DebugOutputCallbacksWide(); 76 | 77 | void LateSymbolInfo::loadMinidump(std::wstring& dumppath, bool delete_when_done) 78 | { 79 | // Method credit to http://stackoverflow.com/a/8119364/21501 80 | 81 | if (debugClient5 || debugControl4 || debugSymbols3) 82 | { 83 | //throw SleepyException(L"Minidump symbols already loaded."); 84 | 85 | // maybe the user moved a .pdb to somewhere where we can now find it? 86 | unloadMinidump(); 87 | } 88 | 89 | IDebugClient *debugClient = NULL; 90 | 91 | SetLastError(0); 92 | comenforce(DebugCreate(__uuidof(IDebugClient), (void**)&debugClient), "DebugCreate"); 93 | comenforce(debugClient->QueryInterface(__uuidof(IDebugClient5 ), (void**)&debugClient5 ), "QueryInterface(IDebugClient5)" ); 94 | comenforce(debugClient->QueryInterface(__uuidof(IDebugControl4), (void**)&debugControl4), "QueryInterface(IDebugControl4)"); 95 | comenforce(debugClient->QueryInterface(__uuidof(IDebugSymbols3), (void**)&debugSymbols3), "QueryInterface(IDebugSymbols3)"); 96 | comenforce(debugClient5->SetOutputCallbacksWide(debugOutputCallbacks), "IDebugClient5::SetOutputCallbacksWide"); 97 | comenforce(debugSymbols3->SetSymbolOptions(SYMOPT_UNDNAME | SYMOPT_LOAD_LINES | SYMOPT_OMAP_FIND_NEAREST | SYMOPT_AUTO_PUBLICS | SYMOPT_DEBUG), "IDebugSymbols::SetSymbolOptions"); 98 | 99 | std::wstring sympath; 100 | prefs.AdjustSymbolPath(sympath, true); 101 | 102 | comenforce(debugSymbols3->SetSymbolPathWide(sympath.c_str()), "IDebugSymbols::SetSymbolPath"); 103 | comenforce(debugClient5->OpenDumpFileWide(dumppath.c_str(), NULL), "IDebugClient4::OpenDumpFileWide"); 104 | comenforce(debugControl4->WaitForEvent(0, INFINITE), "IDebugControl::WaitForEvent"); 105 | 106 | // Since we can't just enumerate all symbols in all modules referenced by the minidump, 107 | // we have to keep the debugger session open and query symbols as requested by the 108 | // profiler GUI. 109 | 110 | debugClient->Release(); // but keep the other ones 111 | 112 | // If we are given a temporary file, clean it up later 113 | if (delete_when_done) 114 | file_to_delete = dumppath; 115 | } 116 | 117 | void LateSymbolInfo::unloadMinidump() 118 | { 119 | if (debugClient5) 120 | { 121 | debugClient5->EndSession(DEBUG_END_ACTIVE_TERMINATE); 122 | debugClient5->Release(); 123 | debugClient5 = NULL; 124 | } 125 | if (debugControl4) 126 | { 127 | debugControl4->Release(); 128 | debugControl4 = NULL; 129 | } 130 | if (debugSymbols3) 131 | { 132 | debugSymbols3->Release(); 133 | debugSymbols3 = NULL; 134 | } 135 | 136 | if (!file_to_delete.empty()) 137 | { 138 | wxRemoveFile(file_to_delete); 139 | file_to_delete.clear(); 140 | } 141 | } 142 | 143 | wchar_t LateSymbolInfo::buffer[4096]; 144 | 145 | void LateSymbolInfo::filterSymbol(Database::Address address, std::wstring &module, std::wstring &procname, std::wstring &sourcefile, unsigned &sourceline) 146 | { 147 | if (debugSymbols3) 148 | { 149 | ULONG moduleindex; 150 | if (debugSymbols3->GetModuleByOffset(address, 0, &moduleindex, NULL) == S_OK) 151 | if (debugSymbols3->GetModuleNameStringWide(DEBUG_MODNAME_MODULE, moduleindex, 0, buffer, _countof(buffer), NULL) == S_OK) 152 | module = buffer; 153 | 154 | if (debugSymbols3->GetNameByOffsetWide(address, buffer, _countof(buffer), NULL, NULL) == S_OK) 155 | { 156 | if (module.compare(buffer) != 0) 157 | { 158 | procname = buffer; 159 | 160 | // Remove redundant "Module!" prefix 161 | size_t modlength = module.length(); 162 | if (procname.length() > modlength+1 && module.compare(0, modlength, procname, 0, modlength)==0 && procname[modlength] == '!') 163 | procname.erase(0, modlength+1); 164 | } 165 | } 166 | 167 | ULONG line; 168 | if (debugSymbols3->GetLineByOffsetWide(address, &line, buffer, _countof(buffer), NULL, NULL) == S_OK) 169 | { 170 | sourcefile = buffer; 171 | sourceline = line; 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/latesymbolinfo.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | latesymbolinfo.h 3 | -------------- 4 | Copyright (C) Vladimir Panteleev 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 | 20 | http://www.gnu.org/copyleft/gpl.html.. 21 | =====================================================================*/ 22 | 23 | #pragma once 24 | 25 | #include 26 | #include 27 | #include "database.h" 28 | 29 | /*===================================================================== 30 | LateSymbolInfo 31 | ---------- 32 | Handles symbols we load after loading a profile capture, 33 | e.g. symbols loaded from included minidumps. 34 | =====================================================================*/ 35 | class LateSymbolInfo 36 | { 37 | public: 38 | LateSymbolInfo(); 39 | ~LateSymbolInfo(); 40 | 41 | void loadMinidump(std::wstring &dumppath, bool delete_when_done); 42 | void unloadMinidump(); 43 | 44 | void filterSymbol(Database::Address address, std::wstring &module, std::wstring &procname, std::wstring &sourcefile, unsigned &sourceline); 45 | 46 | private: 47 | static wchar_t buffer[4096]; 48 | std::wstring file_to_delete; 49 | 50 | // Dbgeng COM objects for minidump symbols 51 | struct IDebugClient5 *debugClient5; 52 | struct IDebugControl4 *debugControl4; 53 | struct IDebugSymbols3 *debugSymbols3; 54 | 55 | 56 | }; 57 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/launchdlg.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | launchdlg.cpp 3 | ---------------- 4 | 5 | Copyright (C) Richard Mitton 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #include "launchdlg.h" 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | BEGIN_EVENT_TABLE(LaunchDlg, wxDialog) 30 | EVT_BUTTON(wxID_OK, LaunchDlg::OnOK) 31 | EVT_BUTTON(ID_CMD_CHOOSE, LaunchDlg::OnChooseCmd) 32 | EVT_BUTTON(ID_CWD_CHOOSE, LaunchDlg::OnChooseCwd) 33 | END_EVENT_TABLE() 34 | 35 | LaunchDlg::LaunchDlg(wxWindow *parent) 36 | : wxDialog(parent, wxID_ANY, "Launch an EXE", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE) 37 | { 38 | wxBeginBusyCursor(); 39 | 40 | wxBoxSizer *rootsizer = new wxBoxSizer( wxVERTICAL ); 41 | wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL ); 42 | 43 | topsizer->Add(new wxStaticText(this, -1, "Enter a command to execute, with any additional arguments."), 0, wxBOTTOM, FromDIP(5)); 44 | 45 | m_cmdctl = new wxTextCtrl(this, -1, "", wxDefaultPosition, FromDIP(wxSize(500, 22))); 46 | wxButton *cmdpick = new wxButton(this, ID_CMD_CHOOSE, "...", wxDefaultPosition, FromDIP(wxSize(22, 22))); 47 | wxBoxSizer *rowsizer = new wxBoxSizer( wxHORIZONTAL ); 48 | rowsizer->Add(m_cmdctl, 0, wxRIGHT, FromDIP(5)); 49 | rowsizer->Add(cmdpick); 50 | 51 | topsizer->Add(rowsizer, 0, wxEXPAND); 52 | topsizer->AddSpacer(FromDIP(10)); 53 | 54 | 55 | topsizer->Add(new wxStaticText(this, -1, "Working directory."), 0, wxBOTTOM, FromDIP(5)); 56 | rowsizer = new wxBoxSizer( wxHORIZONTAL ); 57 | m_cwdctl = new wxTextCtrl(this, -1, "", wxDefaultPosition, FromDIP(wxSize(500, 22))); 58 | rowsizer->Add(m_cwdctl, 0, wxRIGHT, FromDIP(4)); 59 | rowsizer->Add(new wxButton(this, ID_CWD_CHOOSE, "...", wxDefaultPosition, FromDIP(wxSize(22, 22)))); 60 | 61 | topsizer->Add(rowsizer, 0, wxEXPAND); 62 | 63 | 64 | wxSizer *buttons = new wxBoxSizer(wxHORIZONTAL); 65 | buttons->AddStretchSpacer(); 66 | wxButton *ok = new wxButton(this, wxID_OK, "&Launch"); 67 | wxButton *cancel = new wxButton(this, wxID_CANCEL); 68 | buttons->Add(ok, 0, wxLEFT|wxRIGHT, FromDIP(5)); 69 | buttons->Add(cancel, 0, wxLEFT, FromDIP(5)); 70 | topsizer->Add(buttons, 0, wxEXPAND|wxTOP, FromDIP(10)); 71 | 72 | rootsizer->Add(topsizer, 0, wxEXPAND|wxALL, FromDIP(10)); 73 | 74 | SetAutoLayout( true ); 75 | SetSizer( rootsizer ); 76 | 77 | rootsizer->SetSizeHints( this ); 78 | rootsizer->Fit( this ); 79 | 80 | Centre( wxBOTH ); 81 | 82 | m_cmdctl->SetSelection(-1, -1); 83 | m_cmdctl->SetFocus(); 84 | ok->SetDefault(); 85 | 86 | wxEndBusyCursor(); 87 | } 88 | 89 | void LaunchDlg::OnOK(wxCommandEvent& WXUNUSED(event) ) 90 | { 91 | m_cmdvalue = m_cmdctl->GetValue(); 92 | m_cwdvalue = m_cwdctl->GetValue(); 93 | 94 | EndModal(wxID_OK); 95 | } 96 | 97 | void LaunchDlg::OnChooseCmd(wxCommandEvent& WXUNUSED(event) ) 98 | { 99 | wxFileDialog dlg(this, "Choose an exectuable to launch", wxEmptyString, wxEmptyString, 100 | "Executable files (*.exe)|*.exe|All files (*.*)|*.*"); 101 | if (dlg.ShowModal() == wxID_OK) 102 | SetCmdValue(dlg.GetPath()); 103 | } 104 | 105 | void LaunchDlg::OnChooseCwd(wxCommandEvent& WXUNUSED(event) ) 106 | { 107 | wxDirDialog dlg(this, "Choose working directory"); 108 | if (dlg.ShowModal() == wxID_OK) 109 | SetCwdValue(dlg.GetPath()); 110 | } 111 | 112 | void LaunchDlg::SetCmdValue(const wxString& val) 113 | { 114 | m_cmdvalue = val; 115 | 116 | m_cmdctl->SetValue(val); 117 | } 118 | 119 | void LaunchDlg::SetCwdValue(const wxString& val) 120 | { 121 | m_cwdvalue = val; 122 | 123 | m_cwdctl->SetValue(val); 124 | } 125 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/launchdlg.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | launchdlg.h 3 | -------------- 4 | 5 | Copyright (C) Richard Mitton 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #ifndef __LAUNCHDLG_H__ 24 | #define __LAUNCHDLG_H__ 25 | 26 | #include "profilergui.h" 27 | 28 | #define ID_CMD_CHOOSE 1 29 | #define ID_CWD_CHOOSE 2 30 | 31 | class LaunchDlg : public wxDialog 32 | { 33 | public: 34 | LaunchDlg(wxWindow *parent); 35 | 36 | void SetCmdValue(const wxString& val); 37 | void SetCwdValue(const wxString& val); 38 | wxString GetCmdValue() const { return m_cmdvalue; } 39 | wxString GetCwdValue() const { return m_cwdvalue; } 40 | 41 | protected: 42 | wxTextCtrl *m_cmdctl; 43 | wxString m_cmdvalue; 44 | wxTextCtrl *m_cwdctl; 45 | wxString m_cwdvalue; 46 | long m_dialogStyle; 47 | 48 | void OnOK(wxCommandEvent& event); 49 | void OnChooseCmd(wxCommandEvent& event); 50 | void OnChooseCwd(wxCommandEvent& event); 51 | 52 | DECLARE_EVENT_TABLE() 53 | }; 54 | 55 | #endif // __LAUNCHDLG_H__ 56 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/logview.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | logview.cpp 3 | ---------------- 4 | 5 | Copyright (C) Nicholas Chapman, Vladimir Panteleev 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | 24 | #include "logview.h" 25 | #include 26 | #include 27 | #include 28 | 29 | ////////////////////////////////////////////////////////////////////////// 30 | // LogViewLog 31 | ////////////////////////////////////////////////////////////////////////// 32 | 33 | // We can't use the same class for both wxTextCtrl and wxLog, 34 | // because wxWidgets will destroy the active log BEFORE it 35 | // destroys the window. That means we'd be left with a dangling 36 | // pointer in wxWidgets' window hierarchy that we can't do 37 | // anything about. 38 | class LogViewLog : public wxLog 39 | { 40 | LogView *view; 41 | 42 | public: 43 | LogViewLog(LogView *view) 44 | : view(view) 45 | { 46 | } 47 | 48 | virtual LogViewLog::~LogViewLog() 49 | { 50 | // Tell the view that we've been destroyed (by wxWidgets, probably). 51 | view->log = NULL; 52 | // If we are destroyed by wxWidgets, we don't need to worry about 53 | // setting the old log target back - wxWidgets does that. 54 | } 55 | 56 | void DoLogRecord(wxLogLevel level, const wxString& msg, const wxLogRecordInfo& info); 57 | }; 58 | 59 | // Note: we override DoLogRecord instead of DoLogText to avoid the default formatting, 60 | // which includes timestamps. Since the debug engine sends output in line fragments at a time, 61 | // the default formatting would prepend each line fragment with a timestamp, which results 62 | // in a corrupted log. 63 | void LogViewLog::DoLogRecord(wxLogLevel WXUNUSED(level), const wxString& msg, const wxLogRecordInfo& WXUNUSED(info)) 64 | { 65 | wxString str = msg; 66 | 67 | // dbghelp likes to add ASCII backspaces in. (sigh) 68 | // convert them out into newlines. 69 | int backspaceat = -1; 70 | size_t len = str.length(); 71 | for (size_t n=0;nIsFrozen()) 93 | view->Freeze(); 94 | view->AppendText(str); 95 | view->ShowPosition(-1); 96 | 97 | // Update if it's been more than N seconds since our last one. 98 | static DWORD prev = 0; 99 | DWORD now = GetTickCount(); 100 | DWORD diff = now - prev; 101 | if (diff > 500) 102 | forceupdate = true; 103 | 104 | if (forceupdate) 105 | { 106 | prev = now; 107 | if (view->IsFrozen()) 108 | view->Thaw(); 109 | view->Update(); 110 | } 111 | } 112 | 113 | ////////////////////////////////////////////////////////////////////////// 114 | // LogView 115 | ////////////////////////////////////////////////////////////////////////// 116 | 117 | enum 118 | { 119 | // menu items 120 | LogView_Clear = 1, 121 | }; 122 | 123 | BEGIN_EVENT_TABLE(LogView, wxTextCtrl) 124 | EVT_CONTEXT_MENU(LogView::OnContextMenu) 125 | EVT_MENU(wxID_COPY, LogView::OnCopy) 126 | EVT_MENU(LogView_Clear, LogView::OnClearLog) 127 | EVT_MENU(wxID_SELECTALL, LogView::OnSelectAll) 128 | EVT_IDLE(LogView::OnIdle) 129 | END_EVENT_TABLE() 130 | 131 | LogView::LogView(wxWindow *parent) 132 | : wxTextCtrl(parent, 0, "", wxDefaultPosition, parent->FromDIP(wxSize(100,100)), wxTE_MULTILINE|wxTE_READONLY) 133 | { 134 | log = new LogViewLog(this); 135 | previous_log = wxLog::SetActiveTarget(log); 136 | } 137 | 138 | LogView::~LogView() 139 | { 140 | if (log) 141 | { 142 | if (log == wxLog::GetActiveTarget()) 143 | wxLog::SetActiveTarget(previous_log); 144 | delete log; 145 | } 146 | } 147 | 148 | void LogView::OnContextMenu(wxContextMenuEvent& WXUNUSED(event)) 149 | { 150 | wxMenu *menu = new wxMenu; 151 | menu->Append(wxID_COPY, _("&Copy")); 152 | menu->Append(wxID_SELECTALL, _("Select &All")); 153 | menu->Append(LogView_Clear, _("Clear &Log")); 154 | menu->Enable(LogView_Clear, !this->GetValue().empty()); 155 | 156 | PopupMenu(menu); 157 | delete menu; 158 | } 159 | 160 | void LogView::OnCopy(wxCommandEvent& WXUNUSED(event)) 161 | { 162 | Copy(); 163 | } 164 | 165 | void LogView::OnClearLog(wxCommandEvent& WXUNUSED(event)) 166 | { 167 | Clear(); 168 | } 169 | 170 | void LogView::OnSelectAll(wxCommandEvent& WXUNUSED(event)) 171 | { 172 | SetSelection(-1, -1); 173 | } 174 | 175 | void LogView::OnIdle(wxIdleEvent& WXUNUSED(event)) 176 | { 177 | if (IsFrozen()) 178 | Thaw(); 179 | } 180 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/logview.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | logview.h 3 | -------------- 4 | 5 | Copyright (C) Vladimir Panteleev 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #pragma once 24 | 25 | #include 26 | #include 27 | 28 | class LogView : public wxTextCtrl 29 | { 30 | friend class LogViewLog; 31 | 32 | public: 33 | LogView(wxWindow *parent); 34 | virtual ~LogView(); 35 | 36 | void OnContextMenu(wxContextMenuEvent& event); 37 | void OnCopy(wxCommandEvent& event); 38 | void OnClearLog(wxCommandEvent& event); 39 | void OnSelectAll(wxCommandEvent& event); 40 | void OnIdle(wxIdleEvent& event); 41 | 42 | private: 43 | class wxLog *previous_log; 44 | LogViewLog *log; 45 | 46 | DECLARE_EVENT_TABLE() 47 | }; 48 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/mainwin.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | mainwin.h 3 | --------- 4 | File created by ClassTemplate on Sun Mar 13 21:12:40 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | #ifndef __MAINWIN_H_666_ 25 | #define __MAINWIN_H_666_ 26 | 27 | #include "profilergui.h" 28 | #include "proclist.h" 29 | #include "sourceview.h" 30 | #include "CallstackView.h" 31 | #include "logview.h" 32 | #include "threadsview.h" 33 | 34 | #include 35 | #include 36 | 37 | /// Cache per-symbol view settings so we don't 38 | /// have to compute them on every refresh. 39 | struct ViewState 40 | { 41 | std::unordered_set highlighted, filtered; 42 | }; 43 | 44 | /*===================================================================== 45 | MainWin 46 | ------- 47 | 48 | =====================================================================*/ 49 | class MainWin : public wxFrame 50 | { 51 | public: 52 | /*===================================================================== 53 | MainWin 54 | ------- 55 | 56 | =====================================================================*/ 57 | MainWin(const wxString& title, const std::wstring& profilepath, Database *database); 58 | 59 | virtual ~MainWin(); 60 | 61 | // event handlers (these functions should _not_ be virtual) 62 | void OnClose(wxCloseEvent& event); 63 | void OnQuit(wxCommandEvent& event); 64 | void OnNew(wxCommandEvent& event); 65 | void OnOpen(wxCommandEvent& event); 66 | 67 | void OnSaveAs(wxCommandEvent& event); 68 | void OnExportAsCsv(wxCommandEvent& event); 69 | void OnExportAsCallgrind(wxCommandEvent& event); 70 | void OnLoadMinidumpSymbols(wxCommandEvent& event); 71 | void OnCollapseOS(wxCommandEvent& event); 72 | void OnStats(wxCommandEvent& event); 73 | void OnBack(wxCommandEvent& event); 74 | void OnBackUpdate(wxUpdateUIEvent& event); 75 | void OnForward(wxCommandEvent& event); 76 | void OnForwardUpdate(wxUpdateUIEvent& event); 77 | void OnResetToRoot(wxCommandEvent& event); 78 | void OnResetToRootUpdate(wxUpdateUIEvent& event); 79 | void OnResetFilters(wxCommandEvent& event); 80 | void OnFiltersChanged(wxPropertyGridEvent& event); 81 | 82 | void OnDocumentation(wxCommandEvent& event); 83 | void OnSupport(wxCommandEvent& event); 84 | void OnAbout(wxCommandEvent& event); 85 | 86 | /// Called after loading a database 87 | /// (after construction, and in OnOpen). 88 | /// Initialize anything database-specific here. 89 | void reset(); 90 | 91 | /// Refresh proc lists. 92 | /// Preserves selection. 93 | /// Does not reload the database. 94 | void refresh(); 95 | 96 | /// Reload the database. 97 | /// Needed to apply any settings that are applied during 98 | /// database loading, such as collapsing OS calls. 99 | /// Does not refresh(). 100 | void reload(bool loadMinidump=false); 101 | 102 | void clear(); 103 | 104 | /// Switch selection to a given symbol. 105 | /// Does not repopulate the secondary views. 106 | /// Called when clicking on a particular symbol. 107 | void focusSymbol(const Database::AddrInfo *addrinfo); 108 | 109 | /// Inspect a given symbol. 110 | /// Opens the corresponding symbol properties in all related views. 111 | /// Implies focusSymbol(symbol). 112 | /// Called when double-clicking on a particular symbol. 113 | void inspectSymbol(const Database::AddrInfo *addrinfo, bool addtohistory=true); 114 | 115 | void focusThread(Database::ThreadID tid); 116 | 117 | /// Called by SourceView to update the status bar. 118 | void setSourcePos(const std::wstring& currentfile, int currentline); 119 | 120 | const ViewState *getViewState() { return &viewstate; } 121 | 122 | void setFilter(const wxString &name, const wxString &value); 123 | void setHighlight(const std::vector &addresses, bool set); 124 | 125 | void refreshSelectedThreads(); 126 | 127 | /// Non-modal (status bar) progress display 128 | void setProgress(const wchar_t *text, int max=0); 129 | void updateProgress(int pos); 130 | 131 | private: 132 | // any class wishing to process wxWindows events must use this macro 133 | DECLARE_EVENT_TABLE() 134 | 135 | wxPanel* panel; 136 | ProcList* proclist; 137 | ProcList* callers; 138 | ProcList* callees; 139 | ThreadSamplesView *threadSamples; 140 | CallstackView* callStack; 141 | SourceView* sourceview; 142 | LogView* log; 143 | Database *database; 144 | std::wstring profilepath; 145 | 146 | // Used by setSourcePos 147 | std::wstring currentfile; 148 | int currentline; 149 | 150 | wxAuiNotebook *modes; 151 | 152 | wxAuiManager *aui; 153 | wxAuiManager *auiTab1; 154 | wxAuiManager *auiFilter; 155 | wxString contentString; 156 | 157 | wxAuiNotebook *callViews; 158 | wxAuiNotebook *sourceAndLog; 159 | 160 | wxPropertyGrid *filters; 161 | 162 | ThreadsView *threads; 163 | 164 | wxMenuItem *collapseOSCalls; 165 | 166 | ViewState viewstate; 167 | 168 | std::deque history; 169 | size_t historyPos; 170 | 171 | wxGauge *gauge; 172 | 173 | void buildFilterAutocomplete(); 174 | 175 | /// Apply the filter settings in the wxPropertyGrid to viewstate. 176 | void applyFilters(); 177 | void resetFilters(); 178 | 179 | void updateThreads(); 180 | 181 | /// Called when the symbol strings have changed in one way or another. 182 | void symbolsChanged(); 183 | 184 | void showSource(const Database::AddrInfo *addrinfo); 185 | 186 | void updateStatusBar(); 187 | }; 188 | 189 | extern MainWin *theMainWin; 190 | 191 | 192 | 193 | #endif //__MAINWIN_H_666_ 194 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/optionsdlg.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | optionsdlg.h 3 | -------------- 4 | 5 | Copyright (C) Richard Mitton 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #ifndef __OPTIONSDLG_H__ 24 | #define __OPTIONSDLG_H__ 25 | 26 | #include "profilergui.h" 27 | #include 28 | #include 29 | #include 30 | 31 | class wxDirPickerCtrl; 32 | 33 | class OptionsDlg : public wxDialog 34 | { 35 | public: 36 | OptionsDlg(); 37 | virtual ~OptionsDlg(); 38 | 39 | private: 40 | void OnOk( wxCommandEvent & event ); 41 | 42 | void UpdateSymPathButtons(); 43 | void OnSymPath( wxCommandEvent & event ); 44 | void OnSymPathAdd( wxCommandEvent & event ); 45 | void OnSymPathRemove( wxCommandEvent & event ); 46 | void OnSymPathMoveUp( wxCommandEvent & event ); 47 | void OnSymPathMoveDown( wxCommandEvent & event ); 48 | void OnUseSymServer( wxCommandEvent & event ); 49 | void OnSaveMinidump( wxCommandEvent & event ); 50 | 51 | wxListBox *symPaths; 52 | wxButton *symPathAdd, *symPathRemove, *symPathMoveUp, *symPathMoveDown; 53 | wxCheckBox *useSymServer; 54 | wxDirPickerCtrl *symCacheDir; 55 | wxTextCtrl *symServer; 56 | wxCheckBox *saveMinidump; 57 | wxTextCtrl *saveMinidumpTime; 58 | wxRadioButton *mingwWine; 59 | wxRadioButton *mingwDrMingw; 60 | int saveMinidumpTimeValue; 61 | wxSlider *throttle; 62 | 63 | DECLARE_EVENT_TABLE() 64 | }; 65 | 66 | 67 | #endif // __OPTIONSDLG_H__ 68 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/processlist.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | processlist.h 3 | ------------- 4 | File created by ClassTemplate on Sun Mar 20 17:33:43 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | #ifndef __PROCESSLIST_H_666_ 25 | #define __PROCESSLIST_H_666_ 26 | 27 | #include "profilergui.h" 28 | #include "../profiler/processinfo.h" 29 | #include "../utils/sortlist.h" 30 | 31 | // DE: 20090325 ProcessList knows about threadlist and updates it based on process selection 32 | class ThreadList; 33 | class SymbolInfo; 34 | 35 | /*===================================================================== 36 | ProcessList 37 | ----------- 38 | 39 | =====================================================================*/ 40 | class ProcessList : public wxSortedListCtrl 41 | { 42 | public: 43 | /*===================================================================== 44 | ProcessList 45 | ----------- 46 | 47 | =====================================================================*/ 48 | // DE: 20090325 ProcessList knows about threadlist and updates it based on process selection 49 | ProcessList(wxWindow *parent, const wxPoint& pos, 50 | const wxSize& size, 51 | ThreadList* threadList); 52 | 53 | virtual ~ProcessList(); 54 | 55 | void OnSelected(wxListEvent& event); 56 | void OnTimer(wxTimerEvent& event); 57 | void OnSort(wxListEvent& event); 58 | 59 | void updateProcesses(); 60 | void updateTimes(); 61 | void updateThreadList(); 62 | void updateSorting(); 63 | void sortByName(); 64 | void sortByCpuUsage(); 65 | void sortByTotalCpuTime(); 66 | void sortByPID(); 67 | #ifdef _WIN64 68 | void sortByType(); 69 | #endif 70 | void reloadSymbols(bool download); 71 | 72 | const ProcessInfo* getSelectedProcess(); 73 | SymbolInfo* takeSymbolInfo(); 74 | private: 75 | DECLARE_EVENT_TABLE() 76 | 77 | enum { 78 | COL_NAME, 79 | #ifdef _WIN64 80 | COL_TYPE, 81 | #endif 82 | COL_CPUUSAGE, 83 | COL_TOTALCPU, 84 | COL_PID, 85 | NUM_COLUMNS 86 | }; 87 | 88 | std::vector processes; 89 | // DE: 20090325 ProcessList knows about threadlist and updates it based on process selection 90 | ThreadList* threadList; 91 | SymbolInfo *syminfo; 92 | 93 | int selected_process; 94 | wxTimer timer; 95 | wxLongLong lastTime; 96 | int sort_column; 97 | SortType sort_dir; 98 | // DE: 20090325 Update thread list on process selection change, but do it on idle 99 | bool selectionChanged; 100 | bool firstUpdate; 101 | 102 | void fillList(); 103 | }; 104 | 105 | 106 | enum 107 | { 108 | PROCESS_LIST = 4000, 109 | PROCESS_LIST_TIMER = 4001 110 | }; 111 | 112 | 113 | #endif //__PROCESSLIST_H_666_ 114 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/proclist.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | proclist.h 3 | ---------- 4 | File created by ClassTemplate on Tue Mar 15 21:13:18 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | #ifndef __PROCLIST_H_666_ 25 | #define __PROCLIST_H_666_ 26 | 27 | #include "profilergui.h" 28 | #include "database.h" 29 | #include "../utils/sortlist.h" 30 | 31 | /*===================================================================== 32 | ProcList 33 | -------- 34 | 35 | =====================================================================*/ 36 | class ProcList : public wxSortedListCtrl 37 | { 38 | public: 39 | ProcList(wxWindow *parent, bool isroot, Database *database); 40 | 41 | virtual ~ProcList(); 42 | 43 | void OnSelected(wxListEvent& event); 44 | void OnActivated(wxListEvent& event); 45 | void OnSort(wxListEvent& event); 46 | void OnContextMenu(wxContextMenuEvent& event); 47 | 48 | /// Recreates the GUI list from the given one. Preserves selection. 49 | void showList(const Database::List &list); 50 | 51 | void focusSymbol(const Database::Symbol *symbol); 52 | const Database::Symbol *getFocusedSymbol(); 53 | 54 | private: 55 | Database::List list; 56 | 57 | enum ColumnType 58 | { 59 | COL_NAME, 60 | COL_EXCLUSIVE, 61 | COL_INCLUSIVE, 62 | COL_EXCLUSIVEPCT, 63 | COL_INCLUSIVEPCT, 64 | COL_SAMPLES, 65 | COL_CALLSPCT, 66 | COL_MODULE, 67 | COL_SOURCEFILE, 68 | COL_SOURCELINE, 69 | COL_ADDRESS, 70 | MAX_COLUMNS 71 | }; 72 | 73 | struct Column 74 | { 75 | wxString name; 76 | int listctrl_column; 77 | SortType default_sort; 78 | }; 79 | 80 | DECLARE_EVENT_TABLE() 81 | 82 | bool isroot; // Are we the main proc list? 83 | bool updating; // Is a selection update in progress? (ignore selection events) 84 | 85 | Database* database; 86 | int sort_column; 87 | SortType sort_dir; 88 | 89 | Column columns[MAX_COLUMNS]; 90 | void setupColumn(ColumnType id, int width, SortType defsort, const wxString &name); 91 | void setColumnValue(int row, ColumnType id, const wxString &value); 92 | 93 | /// Sorts the in-memory list. Does not affect GUI. 94 | void sortList(); 95 | 96 | /// Displays our in-memory list. Preserves selection. 97 | void displayList(); 98 | }; 99 | 100 | #endif //__PROCLIST_H_666_ 101 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/profilergui.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | profilergui.h 3 | ------------- 4 | File created by ClassTemplate on Sun Mar 13 18:16:34 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | #ifndef __PROFILERGUI_H_666_ 25 | #define __PROFILERGUI_H_666_ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | extern wxIcon sleepy_icon; 45 | 46 | class SymbolInfo; 47 | 48 | enum AttachMode 49 | { 50 | ATTACH_ALL_THREAD, // default 51 | ATTACH_MAIN_THREAD, 52 | ATTACH_MOST_BUSY_THREAD, 53 | }; 54 | 55 | struct AttachInfo 56 | { 57 | AttachInfo(); 58 | ~AttachInfo(); 59 | 60 | HANDLE process_handle; 61 | std::vector thread_handles; 62 | bool attach_all_threads; 63 | SymbolInfo *sym_info; 64 | int limit_profile_time; 65 | }; 66 | 67 | wxBitmap LoadPngResource(const wchar_t *szName, const wxWindowBase* w); 68 | 69 | // Encapsulate a (config) value that can be overridden. 70 | // `T` must be copyable and have a (sensible) default constructor. 71 | template 72 | class OverridableOption 73 | { 74 | public: 75 | OverridableOption() 76 | : is_overridden(false) 77 | {} 78 | 79 | OverridableOption( const T& config_value ) 80 | : config_value(config_value), is_overridden(false) 81 | {} 82 | 83 | // setters 84 | void SetConfigValue( const T& new_value ) 85 | { 86 | is_overridden = false; 87 | config_value = new_value; 88 | } 89 | 90 | void Override( const T& ovr_value ) 91 | { 92 | is_overridden = true; 93 | override_value = ovr_value; 94 | } 95 | 96 | T GetValue() const 97 | { 98 | return is_overridden ? override_value : config_value; 99 | } 100 | 101 | T GetConfigValue() const 102 | { 103 | return config_value; 104 | } 105 | 106 | bool IsOverridden() const { 107 | return is_overridden; 108 | } 109 | 110 | protected: 111 | T config_value; 112 | bool is_overridden; 113 | T override_value; 114 | }; 115 | 116 | class Prefs 117 | { 118 | public: 119 | Prefs() 120 | : useSymServer(false), saveMinidump(-1), throttle(100) 121 | { 122 | useWinePref = useWineSwitch = useMingwSwitch = false; 123 | attachMode = ATTACH_ALL_THREAD; 124 | } 125 | 126 | OverridableOption symSearchPath; 127 | OverridableOption useSymServer; 128 | OverridableOption symCacheDir; 129 | OverridableOption symServer; 130 | OverridableOption saveMinidump; // Save minidump after X seconds. -1 = disabled 131 | OverridableOption throttle; 132 | 133 | bool useWinePref, useWineSwitch, useMingwSwitch; 134 | AttachMode attachMode; 135 | 136 | bool UseWine() 137 | { 138 | return 139 | useMingwSwitch ? false : 140 | useWineSwitch ? true : 141 | useWinePref; 142 | } 143 | 144 | // Add any configured search paths, and the symbol server if enabled. 145 | void AdjustSymbolPath(std::wstring &sympath, bool download) 146 | { 147 | if (!symSearchPath.GetValue().empty()) 148 | { 149 | if (!sympath.empty()) 150 | sympath += L";"; 151 | sympath += symSearchPath.GetValue(); 152 | } 153 | 154 | if (useSymServer.GetValue()) 155 | { 156 | if (!sympath.empty()) 157 | sympath += L";"; 158 | sympath += L"SRV*"; 159 | sympath += symCacheDir.GetValue(); 160 | if ( download ) 161 | sympath += std::wstring(L"*") + symServer.GetValue(); 162 | } 163 | } 164 | 165 | static int ValidateThrottle( int value ) 166 | { 167 | if (value < 1) 168 | return 1; 169 | if (value > 100) 170 | return 100; 171 | return value; 172 | } 173 | }; 174 | 175 | /*===================================================================== 176 | ProfilerGUI 177 | ----------- 178 | the main app 179 | =====================================================================*/ 180 | class ProfilerGUI : public wxApp 181 | { 182 | public: 183 | ProfilerGUI(); 184 | virtual ~ProfilerGUI(); 185 | virtual bool OnInit(); 186 | virtual bool ProcessIdle(); 187 | virtual int OnExit(); 188 | 189 | static void ShowAboutBox(); 190 | static wxString PromptOpen(wxWindow *parent); 191 | 192 | virtual wxAppTraits *CreateTraits(); 193 | 194 | protected: 195 | virtual void OnInitCmdLine(wxCmdLineParser& parser); 196 | virtual bool OnCmdLineParsed(wxCmdLineParser& parser); 197 | 198 | private: 199 | void HandleInit(); 200 | bool Run(); 201 | 202 | void CreateProgressWindow(); 203 | void DestroyProgressWindow(); 204 | 205 | std::wstring LaunchProfiler(const AttachInfo *info); 206 | AttachInfo *RunProcess(const std::wstring &run_cmd, const std::wstring &run_cwd); 207 | AttachInfo *AttachToProcess(const std::wstring& processId); 208 | static void TryLoadSymbols(AttachInfo* output); 209 | void LoadProfileData(const std::wstring &filename); 210 | std::wstring ObtainProfileData(); 211 | 212 | class CaptureWin *captureWin; 213 | bool initialized; 214 | }; 215 | 216 | DECLARE_APP(ProfilerGUI) 217 | 218 | extern Prefs prefs; 219 | extern wxConfig config; 220 | 221 | #endif //__PROFILERGUI_H_666_ 222 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/sourceview.cpp: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | sourceview.cpp 3 | -------------- 4 | File created by ClassTemplate on Tue Mar 15 21:38:06 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | #include "sourceview.h" 25 | 26 | #define countof(_x) (sizeof(_x)/sizeof(_x[0])) 27 | 28 | #include "../utils/stringutils.h" 29 | #include "mainwin.h" 30 | 31 | BEGIN_EVENT_TABLE(SourceView, wxStyledTextCtrl) 32 | EVT_PAINT(SourceView::OnPaint) 33 | EVT_UPDATE_UI(SOURCE_VIEW, SourceView::OnUpdateUI) 34 | END_EVENT_TABLE() 35 | 36 | 37 | StringList keywords(L"keywords.txt"); 38 | 39 | 40 | class MSDevPaths: public std::vector 41 | { 42 | public: 43 | MSDevPaths() 44 | { 45 | int idx=0; 46 | _wgetenv(L""); // initialises _wenviron 47 | 48 | while(wchar_t *env = _wenviron[idx++]) { 49 | if(wcsstr(env,L"COMNTOOLS=") == NULL) 50 | continue; 51 | env = wcschr(env,'='); 52 | if(!env) 53 | continue; 54 | env++; 55 | push_back(std::wstring(env) + L"..\\..\\vc\\crt\\src\\"); 56 | } 57 | } 58 | }; 59 | 60 | MSDevPaths msDevPaths; 61 | 62 | static const int MARGIN_TEXT_STYLE = wxSTC_STYLE_LASTPREDEFINED+1; 63 | 64 | SourceView::SourceView(wxWindow *parent, MainWin* mainwin_) 65 | : wxStyledTextCtrl(parent, SOURCE_VIEW, 66 | wxDefaultPosition, wxDefaultSize, 67 | wxSUNKEN_BORDER, wxEmptyString ), 68 | mainwin(mainwin_) 69 | { 70 | SetUseTabs (false); 71 | SetTabWidth(8); 72 | 73 | reset(); 74 | } 75 | 76 | SourceView::~SourceView() 77 | { 78 | } 79 | 80 | void SourceView::updateText(const wxString& text) 81 | { 82 | SetEditable(true); 83 | SetText(text); 84 | SetEditable(false); 85 | } 86 | 87 | void SourceView::setPlainMode() 88 | { 89 | SetLexer (wxSTC_LEX_NULL); 90 | StyleClearAll(); 91 | 92 | SetMarginWidth (0, 0); 93 | SetMarginWidth (1, 0); 94 | } 95 | 96 | void SourceView::setCppMode() 97 | { 98 | SetLexer (wxSTC_LEX_CPP); 99 | SetKeyWords (0, keywords.Get()); 100 | 101 | StyleClearAll (); 102 | 103 | SetMarginType (0, wxSTC_MARGIN_NUMBER); 104 | SetMarginWidth (0, FromDIP(40)); 105 | StyleSetForeground (wxSTC_STYLE_LINENUMBER, wxColour( 32, 32, 32)); 106 | StyleSetBackground (wxSTC_STYLE_LINENUMBER, wxColour(192,192,192)); 107 | 108 | SetMarginType (1, wxSTC_MARGIN_RTEXT); 109 | SetMarginWidth (1, FromDIP(50)); 110 | StyleSetForeground (MARGIN_TEXT_STYLE, wxColour(255, 0, 0)); 111 | StyleSetBackground (MARGIN_TEXT_STYLE, wxColour(192,192,192)); 112 | 113 | StyleSetForeground (wxSTC_C_DEFAULT, wxColour(0,0,0) ); 114 | StyleSetForeground (wxSTC_C_STRING, wxColour(163,21,21)); 115 | StyleSetForeground (wxSTC_C_PREPROCESSOR, wxColour(0,0,255)); 116 | 117 | StyleSetForeground (wxSTC_C_IDENTIFIER, wxColour(0,0,0)); 118 | 119 | StyleSetForeground (wxSTC_C_WORD, wxColour(0,0,255)); 120 | StyleSetForeground (wxSTC_C_WORD2, wxColour(0,0,255)); 121 | StyleSetForeground (wxSTC_C_NUMBER, wxColour(0,0,0)); 122 | StyleSetForeground (wxSTC_C_CHARACTER, wxColour(0,0,0)); 123 | 124 | StyleSetForeground (wxSTC_C_COMMENT, wxColour(0,128,0)); 125 | StyleSetForeground (wxSTC_C_COMMENTLINE, wxColour(0,128,0)); 126 | StyleSetForeground (wxSTC_C_COMMENTDOC, wxColour(0,128,0)); 127 | StyleSetForeground (wxSTC_C_COMMENTDOCKEYWORD, wxColour(0,128,0)); 128 | StyleSetForeground (wxSTC_C_COMMENTDOCKEYWORDERROR, wxColour(0,128,0)); 129 | StyleSetBold(wxSTC_C_WORD, true); 130 | StyleSetBold(wxSTC_C_WORD2, true); 131 | StyleSetBold(wxSTC_C_COMMENTDOCKEYWORD, true); 132 | 133 | for (int i = wxSTC_C_DEFAULT; i <= wxSTC_C_PREPROCESSORCOMMENT; ++i) 134 | { 135 | wxFont font(wxFontInfo(10).FaceName("Consolas")); 136 | StyleSetFont(i, font); 137 | } 138 | } 139 | 140 | void SourceView::showFile(std::wstring path, int proclinenum, const std::vector &linecounts) 141 | { 142 | currentfile = path; 143 | 144 | // Don't show error messages with CPP highlighting 145 | setPlainMode(); 146 | if (path == "[hint KiFastSystemCallRet]") 147 | { 148 | updateText( 149 | " Hint: KiFastSystemCallRet often means the thread was waiting for something else to finish.\n" 150 | " \n" 151 | " Possible causes might be disk I/O, waiting for an event, or maybe just calling Sleep().\n" 152 | ); 153 | return; 154 | } 155 | 156 | if (path == "" || path == "[unknown]") 157 | { 158 | updateText("[ No source file available for this location. ]"); 159 | return; 160 | } 161 | 162 | 163 | FILE *file = _wfopen(path.c_str(),L"r, ccs=UNICODE"); 164 | if(!file) 165 | { 166 | wchar_t *crtSub = L"\\crt\\src\\"; 167 | wchar_t *crt = wcsstr((wchar_t *)path.c_str(), crtSub); 168 | if(crt) { 169 | for(size_t i=0;isetSourcePos(currentfile, line); 249 | 250 | event.Skip(); 251 | } 252 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/sourceview.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | sourceview.h 3 | ------------ 4 | File created by ClassTemplate on Tue Mar 15 21:38:06 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | #ifndef __SOURCEVIEW_H_666_ 25 | #define __SOURCEVIEW_H_666_ 26 | 27 | #include "profilergui.h" 28 | 29 | #include 30 | 31 | class MainWin; 32 | 33 | /*===================================================================== 34 | SourceView 35 | ---------- 36 | 37 | =====================================================================*/ 38 | class SourceView : public wxStyledTextCtrl 39 | { 40 | public: 41 | /*===================================================================== 42 | SourceView 43 | ---------- 44 | 45 | =====================================================================*/ 46 | SourceView(wxWindow *parent, MainWin* mainwin); 47 | 48 | virtual ~SourceView(); 49 | 50 | void OnPaint(wxPaintEvent& event); 51 | void OnUpdateUI(wxUpdateUIEvent& event); 52 | 53 | void showFile(std::wstring path, int linenum, const std::vector &linecounts); 54 | void reset(); 55 | 56 | const std::wstring& getCurrentFile() const { return currentfile; } 57 | private: 58 | void setPlainMode(); 59 | void setCppMode(); 60 | void updateText(const wxString& text); 61 | 62 | std::wstring currentfile; 63 | MainWin* mainwin; 64 | 65 | DECLARE_EVENT_TABLE() 66 | 67 | }; 68 | 69 | enum 70 | { 71 | SOURCE_VIEW = 1005 72 | }; 73 | 74 | 75 | #endif //__SOURCEVIEW_H_666_ 76 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/threadlist.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | threadlist.h 3 | ------------- 4 | File created by ClassTemplate on Sun Mar 20 17:33:43 2005 5 | 6 | Copyright (C) Dan Engelbrecht 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | #ifndef __THREADSLIST_H_666_ 25 | #define __THREADSLIST_H_666_ 26 | 27 | #include "profilergui.h" 28 | #include "../profiler/threadinfo.h" 29 | #include "../profiler/processinfo.h" 30 | #include "../utils/sortlist.h" 31 | 32 | #include 33 | class SymbolInfo; 34 | 35 | /*===================================================================== 36 | ThreadsList 37 | ----------- 38 | 39 | =====================================================================*/ 40 | class ThreadList : public wxSortedListCtrl 41 | { 42 | public: 43 | /*===================================================================== 44 | ThreadList 45 | ----------- 46 | 47 | =====================================================================*/ 48 | ThreadList(wxWindow *parent, const wxPoint& pos, 49 | const wxSize& size, wxButton *ok_button, wxButton *all_button); 50 | 51 | virtual ~ThreadList(); 52 | 53 | void OnSelected(wxListEvent& event); 54 | void OnDeSelected(wxListEvent& event); 55 | void OnTimer(wxTimerEvent& event); 56 | void OnSort(wxListEvent& event); 57 | 58 | void updateThreads(const ProcessInfo* processInfo, SymbolInfo *symInfo); 59 | void updateTimes(); 60 | void updateSorting(); 61 | void sortByLocation(); 62 | void sortByCpuUsage(); 63 | void sortByTotalCpuTime(); 64 | void sortByID(); 65 | void sortByName(); 66 | 67 | std::vector getSelectedThreads(bool all=false); 68 | private: 69 | DECLARE_EVENT_TABLE() 70 | 71 | enum { 72 | COL_LOCATION, 73 | COL_CPUUSAGE, 74 | COL_TOTALCPU, 75 | COL_ID, 76 | COL_NAME, 77 | NUM_COLUMNS 78 | }; 79 | 80 | std::vector threads; 81 | std::set selected_threads; 82 | wxTimer timer; 83 | wxLongLong lastTime; 84 | int sort_column; 85 | SortType sort_dir; 86 | HANDLE process_handle; 87 | SymbolInfo *syminfo; 88 | wxButton *ok_button; 89 | wxButton *all_button; 90 | 91 | void fillList(); 92 | int getNumDisplayedThreads(); 93 | std::wstring getLocation(HANDLE thread_handle, DWORD thread_id); 94 | }; 95 | 96 | 97 | enum 98 | { 99 | THREADS_LIST = 4000, 100 | THREADS_LIST_TIMER = 4001 101 | }; 102 | 103 | 104 | #endif //__PROCESSLIST_H_666_ 105 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/threadpicker.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | threadpicker.h 3 | -------------- 4 | File created by ClassTemplate on Sun Mar 20 17:12:56 2005 5 | 6 | Copyright (C) Nicholas Chapman 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | 22 | http://www.gnu.org/copyleft/gpl.html. 23 | =====================================================================*/ 24 | #ifndef __THREADPICKER_H_666_ 25 | #define __THREADPICKER_H_666_ 26 | 27 | #include "profilergui.h" 28 | #include "processlist.h" 29 | #include "logview.h" 30 | #include 31 | 32 | #include 33 | #include 34 | 35 | // DE: 20090325 Include for list to pick thread(s) 36 | #include "threadlist.h" 37 | 38 | class wxModalFrame : public wxFrame 39 | { 40 | public: 41 | wxModalFrame() { m_evtLoop = NULL; m_retCode = -1; } 42 | wxModalFrame::wxModalFrame(wxWindow *parent, 43 | wxWindowID id, 44 | const wxString& title, 45 | const wxPoint& pos = wxDefaultPosition, 46 | const wxSize& size = wxDefaultSize, 47 | long style = wxDEFAULT_FRAME_STYLE, 48 | const wxString& name = wxFrameNameStr) 49 | : wxFrame(parent, id, title, pos, size, style, name) 50 | { 51 | m_evtLoop = NULL; m_retCode = -1; 52 | modal = false; 53 | } 54 | 55 | int ShowModal() 56 | { 57 | modal = true; 58 | Show(); 59 | 60 | m_evtLoop = new wxModalEventLoop(this); 61 | m_evtLoop->Run(); 62 | delete m_evtLoop; 63 | m_evtLoop = NULL; 64 | 65 | Hide(); 66 | return m_retCode; 67 | } 68 | 69 | void EndModal(int retCode) 70 | { 71 | modal = false; 72 | m_retCode = retCode; 73 | m_evtLoop->Exit(); 74 | } 75 | 76 | bool IsModal() const { return modal; } 77 | 78 | protected: 79 | wxModalEventLoop *m_evtLoop; 80 | int m_retCode; 81 | bool modal; 82 | }; 83 | 84 | class ThreadPicker : public wxModalFrame 85 | { 86 | public: 87 | enum Mode { QUIT, OPEN, ATTACH, RUN }; 88 | 89 | ThreadPicker(); 90 | virtual ~ThreadPicker(); 91 | 92 | bool TryAttachToProcess(bool allThreads); 93 | void AttachToProcess(bool allThreads); 94 | void UpdateSorting(); 95 | 96 | void OnOpen(wxCommandEvent& event); 97 | void OnClose(wxCloseEvent& event); 98 | void OnQuit(wxCommandEvent& event); 99 | void OnRefresh(wxCommandEvent& event); 100 | void OnOptions(wxCommandEvent& event); 101 | void OnDownload(wxCommandEvent& event); 102 | void OnLaunchExe(wxCommandEvent& event); 103 | void OnDocumentation(wxCommandEvent& event); 104 | void OnSupport(wxCommandEvent& event); 105 | void OnAbout(wxCommandEvent& event); 106 | void OnAttachProfiler(wxCommandEvent& event); 107 | void OnAttachProfilerAll(wxCommandEvent& event); 108 | void OnDoubleClicked(wxListEvent& event); 109 | void OnTimeCheck(wxCommandEvent& event); 110 | 111 | AttachInfo *attach_info; 112 | std::wstring run_filename, run_cwd, open_filename; 113 | LogView *log; 114 | wxCheckBox *time_check; 115 | wxTextCtrl *time_ctrl; 116 | int time_value; 117 | wxIntegerValidator* time_validator; 118 | 119 | private: 120 | ProcessList* processlist; 121 | 122 | // DE: 20090325 Include for list to pick thread(s) 123 | ThreadList* threadlist; 124 | wxBitmap* bitmap; 125 | 126 | DECLARE_EVENT_TABLE() 127 | }; 128 | 129 | 130 | 131 | 132 | 133 | #endif //__THREADPICKER_H_666_ 134 | -------------------------------------------------------------------------------- /src/wxProfilerGUI/threadsview.h: -------------------------------------------------------------------------------- 1 | /*===================================================================== 2 | threadsview.h 3 | ------------ 4 | 5 | Copyright (C) Very Sleepy authors and contributors 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 20 | 21 | http://www.gnu.org/copyleft/gpl.html. 22 | =====================================================================*/ 23 | #ifndef __THREADSVIEW_H_666_ 24 | #define __THREADSVIEW_H_666_ 25 | 26 | #include "database.h" 27 | #include "../utils/sortlist.h" 28 | 29 | class ThreadsView : public wxSortedListCtrl 30 | { 31 | public: 32 | ThreadsView(wxWindow *parent, Database *database); 33 | virtual ~ThreadsView(); 34 | 35 | void OnSelected(wxListEvent &event); 36 | void OnDeSelected(wxListEvent &event); 37 | void OnSort(wxListEvent &event); 38 | void OnTimer(wxTimerEvent &event); 39 | 40 | void updateList(); 41 | 42 | std::vector getSelectedThreads(); 43 | void clearSelectedThreads(); 44 | 45 | void focusThread(Database::ThreadID tid); 46 | 47 | private: 48 | enum ColumnType { 49 | COL_TID, 50 | COL_NAME, 51 | MAX_COLUMNS, 52 | }; 53 | 54 | DECLARE_EVENT_TABLE() 55 | 56 | struct ThreadRow { 57 | Database::ThreadID tid; 58 | std::wstring name; 59 | }; 60 | 61 | std::vector threads; 62 | 63 | Database *database; 64 | int sort_column; 65 | SortType sort_dir; 66 | wxTimer selectionTimer; 67 | 68 | void startSelectionTimer(); 69 | void getThreadsFromDatabase(); 70 | void sortThreads(); 71 | void fillList(); 72 | }; 73 | 74 | class ThreadSamplesView : public wxSortedListCtrl 75 | { 76 | public: 77 | ThreadSamplesView(wxWindow *parent, Database *database); 78 | virtual ~ThreadSamplesView(); 79 | 80 | void OnSort(wxListEvent &event); 81 | void OnActivated(wxListEvent &event); 82 | 83 | void showList(Database::SymbolSamples const &symbolSamples); 84 | void reset(); 85 | 86 | private: 87 | enum ColumnType { 88 | COL_TID, 89 | COL_NAME, 90 | COL_EXCLUSIVE, 91 | COL_INCLUSIVE, 92 | COL_EXCLUSIVEPCT, 93 | COL_INCLUSIVEPCT, 94 | MAX_COLUMNS, 95 | }; 96 | 97 | DECLARE_EVENT_TABLE() 98 | 99 | struct ThreadRow { 100 | Database::ThreadID tid; 101 | std::wstring name; 102 | double exclusive, inclusive; 103 | }; 104 | 105 | double totalCount; 106 | std::vector threads; 107 | 108 | Database *database; 109 | int sort_column; 110 | SortType sort_dir; 111 | 112 | void sortThreads(); 113 | void fillList(); 114 | }; 115 | 116 | enum { 117 | THREADS_VIEW = 5107, 118 | THREADS_VIEW_TIMER, 119 | THREAD_SAMPLES_VIEW, 120 | }; 121 | 122 | #endif // __THREADSVIEW_H_666_ 123 | -------------------------------------------------------------------------------- /thirdparty/.gitignore: -------------------------------------------------------------------------------- 1 | /drmingw_build_32/ 2 | /drmingw_build_64/ 3 | -------------------------------------------------------------------------------- /thirdparty/drmingw_build_mingw.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enabledelayedexpansion 3 | 4 | rem This batch file attempts to build Dr. MinGW in a way 5 | rem that's compatible with Very Sleepy's project file. 6 | 7 | rem Find 7-Zip. 8 | 9 | if not defined 7ZIP for %%a in (7z.exe) do if not [%%~$PATH:a] == [] set 7ZIP="%%~$PATH:a" 10 | if not defined 7ZIP if exist "!ProgramFiles!\7-Zip\7z.exe" set 7ZIP="!ProgramFiles!\7-Zip\7z.exe" 11 | if not defined 7ZIP if exist "!ProgramFiles(x86)!\7-Zip\7z.exe" set 7ZIP="!ProgramFiles(x86)!\7-Zip\7z.exe" 12 | if not defined 7ZIP if exist "!SystemDrive!\7-Zip\7z.exe" set 7ZIP="!SystemDrive!\7-Zip\7z.exe" 13 | if not defined 7ZIP echo drmingw_build: Can't find 7-Zip installation - please add it to PATH or specify the full path to 7z.exe in the 7ZIP environment variable. & exit /b 1 14 | echo drmingw_build: Found 7-Zip at !7ZIP! 15 | 16 | rem Download MinGW. 17 | 18 | set MINGW32_FN=i686-6.3.0-release-win32-dwarf-rt_v5-rev1.7z 19 | set MINGW64_FN=x86_64-6.3.0-release-win32-seh-rt_v5-rev1.7z 20 | 21 | set MINGW32_URL=https://sourceforge.net/projects/mingw-w64/files/Toolchains%%20targetting%%20Win32/Personal%%20Builds/mingw-builds/6.3.0/threads-win32/dwarf/%MINGW32_FN%/download 22 | set MINGW64_URL=https://sourceforge.net/projects/mingw-w64/files/Toolchains%%20targetting%%20Win64/Personal%%20Builds/mingw-builds/6.3.0/threads-win32/seh/%MINGW64_FN%/download 23 | 24 | for %%t in (32 64) do ( 25 | set FN=!MINGW%%t_FN! 26 | set URL=!MINGW%%t_URL! 27 | 28 | if not exist "%~dp0\mingw\!FN!" ( 29 | echo Downloading !FN!... 30 | set DEST=%~dp0/mingw/!FN! 31 | REM If the automagic download fails, download the files manually and put them in this directory. 32 | call :download 33 | if errorlevel 1 exit /b 1 34 | ) 35 | if not exist "%~dp0\mingw\mingw%%t" !7ZIP! x -o"%~dp0\mingw" %~dp0/mingw/!FN! 36 | ) 37 | 38 | rem Find CMake. 39 | 40 | if not defined CMAKE for %%a in (cmake.exe) do ( 41 | set CMAKE_EXE=%%~$PATH:a 42 | if not [!CMAKE_EXE!] == [] for %%b in ("!CMAKE_EXE!") do ( 43 | set CMAKE_BIN=%%~dpb 44 | for %%c in ("!CMAKE_BIN:~0,-1!") do set CMAKE=%%~dpc 45 | ) 46 | ) 47 | 48 | if not defined CMAKE if exist "!ProgramFiles!\CMake" set CMAKE=!ProgramFiles!\CMake 49 | if not defined CMAKE if exist "!ProgramFiles(x86)!\CMake" set CMAKE=!ProgramFiles(x86)!\CMake 50 | if not defined CMAKE if exist "!SystemDrive!\CMake" set CMAKE=!SystemDrive!\CMake 51 | if not defined CMAKE echo drmingw_build: Can't find CMake installation - please add it to PATH or specify the path to it in the CMAKE environment variable. & exit /b 1 52 | echo drmingw_build: Found CMake at !CMAKE! 53 | 54 | rem Build! 55 | 56 | for %%t in (32 64) do ( 57 | set TARGET=%%t 58 | echo drmingw_build: Building for mingw!TARGET! 59 | 60 | cd "%~dp0" 61 | if not exist drmingw_build_!TARGET! mkdir drmingw_build_!TARGET! 62 | cd drmingw_build_!TARGET! 63 | 64 | rem Clear and rebuild PATH to ensure that nothing may contaminate it. 65 | set PATH=%~dp0\mingw\mingw!TARGET!\bin;!CMAKE!\bin;!WinDir!\System32 66 | set MAKE= 67 | set CC= 68 | 69 | if not exist Makefile cmake -G "MinGW Makefiles" ..\drmingw 70 | if errorlevel 1 exit /b 1 71 | 72 | cmake --build . --target mgwhelp 73 | if errorlevel 1 exit /b 1 74 | ) 75 | if errorlevel 1 exit /b 1 76 | 77 | echo drmingw_build: Done! 78 | goto :eof 79 | 80 | :download 81 | 82 | rem Download !URL! to !DEST!. 83 | rem Note: Positional parameters don't work here, as the percent signs in URLs are eagerly interpreted despite quoting. 84 | 85 | @echo Downloading !URL! 86 | @echo !DEST! 87 | 88 | for %%a in (powershell.exe) do if not [%%~$PATH:a] == [] powershell -Command "(New-Object Net.WebClient).DownloadFile('!URL!', '!DEST!')" & goto :eof 89 | for %%a in (curl.exe) do if not [%%~$PATH:a] == [] curl "!URL!" -O "!DEST!" --location & goto :eof 90 | for %%a in (wget.exe) do if not [%%~$PATH:a] == [] wget "!URL!" -o "!DEST!" --max-redirect=5 & goto :eof 91 | for %%a in (bitsadmin.exe) do if not [%%~$PATH:a] == [] start /wait "MinGW download" bitsadmin /transfer "MinGW" "!URL!" "!DEST!" & goto :eof 92 | echo No download utilities available - please download file at !URL! and save to !DEST! manually 93 | exit /b 1 94 | -------------------------------------------------------------------------------- /thirdparty/drmingw_build_msys2.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal enabledelayedexpansion 3 | 4 | rem This batch file attempts to build Dr. MinGW using MSys2 5 | rem (https://msys2.github.io/) in a way that's compatible with Very 6 | rem Sleepy's project file. 7 | 8 | rem Note that this method is not recommended - currently, MSys2 only 9 | rem packages MinGW with POSIX threads, whereas Dr. MinGW is 10 | rem recommended to be built with Win32 threads. Using POSIX threads 11 | rem will result in lower performance and a dependency to 12 | rem libwinpthread-1.dll (which can manifest in an error message such 13 | rem as "Could not load dbghelpdr.dll: %1 is not a valid Win32 14 | rem application" in Very Sleepy). 15 | 16 | rem You can run: 17 | rem $ pacman -S --needed mingw-w64-{i686,x86_64}-{gcc,make} 18 | rem in the MSys2 shell to install the necessary MSys2 packages. 19 | 20 | rem Find MSys2. 21 | 22 | if not defined MSYS2 for %%a in (mingw32-make.exe) do ( 23 | set MSYS2_EXE=%%~$PATH:a 24 | if not [!MSYS2_EXE!] == [] for %%b in ("!MSYS2_EXE!") do ( 25 | set MSYS2_BIN=%%~dpb 26 | for %%c in ("!MSYS2_BIN:~0,-1!") do ( 27 | set MSYS2_MGW=%%~dpc 28 | for %%d in ("!MSYS2_MGW:~0,-1!") do set MSYS2=%%~dpd 29 | ) 30 | ) 31 | ) 32 | 33 | if not defined MSYS2 if exist "!SystemDrive!\msys64" set MSYS2="!SystemDrive!\msys64" 34 | 35 | if not defined MSYS2 echo drmingw_build: Can't find MSys2 installation - please add it to PATH or specify the path to it in the MSYS2 environment variable. & exit /b 1 36 | 37 | echo drmingw_build: Found MSys2 at !MSYS2! 38 | 39 | rem Find CMake. 40 | 41 | if not defined CMAKE for %%a in (cmake.exe) do ( 42 | set CMAKE_EXE=%%~$PATH:a 43 | if not [!CMAKE_EXE!] == [] for %%b in ("!CMAKE_EXE!") do ( 44 | set CMAKE_BIN=%%~dpb 45 | for %%c in ("!CMAKE_BIN:~0,-1!") do set CMAKE=%%~dpc 46 | ) 47 | ) 48 | 49 | if not defined CMAKE if exist "!ProgramFiles!\CMake" set CMAKE=!ProgramFiles!\CMake 50 | 51 | if not defined CMAKE if exist "!ProgramFiles(x86)!\CMake" set CMAKE=!ProgramFiles(x86)!\CMake 52 | 53 | if not defined CMAKE if exist "!SystemDrive!\CMake" set CMAKE=!SystemDrive!\CMake 54 | 55 | if not defined CMAKE echo drmingw_build: Can't find CMake installation - please add it to PATH or specify the path to it in the CMAKE environment variable. & exit /b 1 56 | 57 | echo drmingw_build: Found CMake at !CMAKE! 58 | 59 | rem Build! 60 | 61 | for %%t in (32 64) do ( 62 | set TARGET=%%t 63 | echo drmingw_build: Building for mingw!TARGET! 64 | 65 | cd "%~dp0" 66 | if not exist drmingw_build_!TARGET! mkdir drmingw_build_!TARGET! 67 | cd drmingw_build_!TARGET! 68 | 69 | rem Clear and rebuild PATH to ensure that nothing may contaminate it. 70 | set PATH=!MSYS2!\mingw!TARGET!\bin;!CMAKE!\bin;!WinDir!\System32 71 | set MAKE= 72 | set CC= 73 | 74 | if not exist Makefile cmake -G "MinGW Makefiles" ..\drmingw 75 | if errorlevel 1 exit /b 1 76 | 77 | cmake --build . --target mgwhelp 78 | if errorlevel 1 exit /b 1 79 | ) 80 | if errorlevel 1 exit /b 1 81 | 82 | echo drmingw_build: Done! 83 | -------------------------------------------------------------------------------- /thirdparty/mingw/.gitignore: -------------------------------------------------------------------------------- 1 | /*.7z 2 | /mingw32/ 3 | /mingw64/ 4 | -------------------------------------------------------------------------------- /thirdparty/wxWidgetsSetup/.gitignore: -------------------------------------------------------------------------------- 1 | /Release/ 2 | -------------------------------------------------------------------------------- /thirdparty/wxWidgetsSetup/wxWidgetsSetup.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Release 6 | Win32 7 | 8 | 9 | 10 | {941F452F-6510-4BF2-AE25-9EE32FEFD51D} 11 | wxWidgetsSetup 12 | 13 | 14 | 15 | 16 | 17 | copy /Y setup.h ..\wxWidgets\include\wx\setup.h 18 | Copying wxWidgets setup file 19 | ..\wxWidgets\include\wx\setup.h 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /thirdparty/wxWidgetsSetup/wxWidgetsSetup.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | --------------------------------------------------------------------------------