{"id":20426996,"url":"https://github.com/juangburgos/qcrashhandler","last_synced_at":"2025-07-29T19:44:35.028Z","repository":{"id":70896261,"uuid":"220295882","full_name":"juangburgos/QCrashHandler","owner":"juangburgos","description":"Small library to use breakpad with Qt C++","archived":false,"fork":false,"pushed_at":"2024-08-14T08:28:21.000Z","size":318,"stargazers_count":35,"open_issues_count":1,"forks_count":15,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-09T21:51:06.549Z","etag":null,"topics":["breakpad","c-plus-plus","cpp","minidump","qt","qt5"],"latest_commit_sha":null,"homepage":null,"language":"QMake","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/juangburgos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-07T17:46:13.000Z","updated_at":"2024-09-24T01:29:11.000Z","dependencies_parsed_at":"2023-03-11T09:27:05.431Z","dependency_job_id":null,"html_url":"https://github.com/juangburgos/QCrashHandler","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juangburgos%2FQCrashHandler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juangburgos%2FQCrashHandler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juangburgos%2FQCrashHandler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juangburgos%2FQCrashHandler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/juangburgos","download_url":"https://codeload.github.com/juangburgos/QCrashHandler/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230537062,"owners_count":18241515,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["breakpad","c-plus-plus","cpp","minidump","qt","qt5"],"created_at":"2024-11-15T07:18:24.787Z","updated_at":"2024-12-20T05:08:51.887Z","avatar_url":"https://github.com/juangburgos.png","language":"QMake","funding_links":[],"categories":[],"sub_categories":[],"readme":"## How to Use\n\n### With *CMake* projects:\nAdd subdirectory `./src` from this repository to your project's `CMakeLists.txt` and enable `ASM` language when on Unix:\n```cmake\nif(UNIX)\n    enable_language(ASM)\nendif(UNIX)\n\nadd_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../src)\n```\nAdd `QCrashHandler` library to your target:\n```camke\ntarget_link_libraries(\u003ctarget\u003e ... QCrashHandler ...)\n```\nFor release builds select [RelWithDebInfo](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html) build type.\n\n### With *qmake* projects:\nIn your *Qt* project file (`*.pro`) simply *include* the `./src/qcrashhandler.pri` file from this repository:\n\n```cmake\ninclude($$PWD/../src/qcrashhandler.pri)\n```\n\nFor release builds make sure to configure the project to create the debug symbols, for example:\n\n```cmake\nCONFIG(debug, debug|release) {\n    TARGET = testd\n} else {\n    TARGET = test\n    # create debug symbols for release builds\n    CONFIG *= force_debug_info\n    QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO -= -O2\n}\n```\n### Usage in code\nThe on your `main` function create and intialize the crash handler, *after* creating the `QApplication` object;\n\n```c++\nint main(int argc, char *argv[])\n{\n    QCoreApplication a(argc, argv);\n\n    // write the dumps in the user's desktop:\n    Breakpad::CrashHandler::instance()-\u003eInit(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation));\n\n    // ... other stuff\n\n    return a.exec();\n}\n```\n\nAnd that's it! The application will write dump files to the specified location whenever a crash occurs.\n\n## Commandline Analysis\n\nFirst compile necessary breakpad binaries using `gcc` (use **MSys2** on *Windows*).\n\n```bash\nwhich gcc\n\ncd ${PWD}/deps/breakpad.git\n./configure\nmake\n\ncd ../../\n```\n\nAdd to `PATH` necessary binary directories.\n\n```bash\n# on windows\nPATH=\"${PATH}:${PWD}/deps/breakpad.git/src/tools/windows/binaries\"\nPATH=\"${PATH}:${PWD}/deps/breakpad.git/src/processor\"\n\n# on linux\nPATH=\"${PATH}:${PWD}/deps/breakpad.git/src/tools/linux/dump_syms\"\nPATH=\"${PATH}:${PWD}/deps/breakpad.git/src/processor\"\nPATH=\"${PATH}:${PWD}/deps/breakpad.git/src/tools/linux/core2md\"\nPATH=\"${PATH}:${PWD}/deps/breakpad.git/src/tools/linux/md2core\"\n\n# check\nwhich dump_syms\nwhich minidump_stackwalk\n```\n\nCreate symbols file, on windows the `*.pdb` file is required (more on this later), and on linux the binary file compiled with debug symbols is required.\n\n```bash\n# on windows\ndump_syms test.pdb \u003e test.sym\n# on linux (binary/esecutable, could be *.so file)\ndump_syms test \u003e test.sym\n# run a dummy stack walk over the dump file to see where is the symbols file expected to be\nminidump_stackwalk test.dmp symbols 2\u003e\u00261 | grep test.sym\n# ... INFO: No symbol file at ./symbols/test.pdb/XXXXX/test.sym\n# create expected directory\nmkdir -p ./symbols/test.pdb/XXXXX\n# move symbols file to expected location\nmv test.sym ./symbols/test.pdb/XXXXX/test.sym\n# finally run the stack walk\nminidump_stackwalk ./test.dmp symbols \u003e test_analysis.txt\n```\n\nShow show call stack starting with the crash on the top:\n\n```\n 1  Qt5Cored.dll + 0xbc531\n    rsp = 0x000000c2132ffb90   rip = 0x000000005d1ac531\n    Found by: stack scanning\n 2  test.exe!QString::`scalar deleting destructor'(unsigned int) + 0x18\n    rsp = 0x000000c2132ffbb0   rip = 0x00007ff6f1554148\n    Found by: stack scanning\n 3  test.exe!buggyFunc() [main.cpp : 7 + 0x2b]\n    rsp = 0x000000c2132ffbe0   rip = 0x00007ff6f155403f\n    Found by: call frame info\n 4  test.exe!main [main.cpp : 19 + 0x5]\n    rsp = 0x000000c2132ffc30   rip = 0x00007ff6f15540d1\n    Found by: call frame info\n```\n\nThere are references to `main.cpp` and line numbers which provide useful information about the crash.\n\n**NOTE** : on windows we need a `*.pdb` file for release builds. To export debug symbols for release builds in **Qt** simply add to the `*.pro` project file:\n\n```cmake\nCONFIG *= force_debug_info\nQMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO -= -O2\n```\n\nAlternatively, symbols for *Release* versions can be obtained by configuring the *Visual Studio* project as follows:\n\n* Open the **Properties** dialog box for the project.\n\n* Click the **C/C++** node. Set **Debug Information Format** to `Program Database (/Zi)`.\n\n* Select the **Optimization** node. Set **Optimization** to `Disabled (/Od)`.\n\n* Expand **Linker** and click the **General** node. Set **Enable Incremental Linking** to `No (/INCREMENTAL:NO)`.\n\n* Select the **Debugging** node. Set **Generate Debug Info** to `Yes (/DEBUG)`.\n\n* Select the **Optimization** node. Set **References** to `/OPT:REF`.\n\n### Script\n\nA [`bash` script was developed](./src/qcrashdumper) to automate the analysis of dump `*.dmp` files. It can be added to the `PATH` for ease of use, e,g,:\n\n```bash\nPATH=\"${PATH}:${PWD}/src/\"\nwhich qcrashdumper\n# pass minidump as first argument\nqcrashdumper test.dmp /path/to/pdbfiles\n```\n\n---\n\n## Windows Errors\n\nThe `dump_syms.exe` tool provided by the Windows distribution of breakpad sometimes does not generate the symbols and displays an error similar to:\n\n```\nCoCreateInstance CLSID_DiaSource {E6756135-1E65-4D17-8576-610761398C3C} failed (msdia*.dll unregistered?)\nOpen failed\n```\n\nThis is because requires an specific `*.dll` from some Visual Studio version registered on the system. Looking at the source code of `pdb_source_line_writer.cc`, the following lines:\n\n```c++\nclass DECLSPEC_UUID(\"B86AE24D-BF2F-4ac9-B5A2-34B14E4CE11D\") DiaSource100;\nclass DECLSPEC_UUID(\"761D3BCD-1304-41D5-94E8-EAC54E4AC172\") DiaSource110;\nclass DECLSPEC_UUID(\"3BFCEA48-620F-4B6B-81F7-B9AF75454C7D\") DiaSource120;\nclass DECLSPEC_UUID(\"E6756135-1E65-4D17-8576-610761398C3C\") DiaSource140;\n\n// If the CoCreateInstance call above failed, msdia*.dll is not registered.\n// We can try loading the DLL corresponding to the #included DIA SDK, but\n// the DIA headers don't provide a version. Lets try to figure out which DIA\n// version we're compiling against by comparing CLSIDs.\nconst wchar_t *msdia_dll = nullptr;\nif (CLSID_DiaSource == _uuidof(DiaSource100)) {\nmsdia_dll = L\"msdia100.dll\";\n} else if (CLSID_DiaSource == _uuidof(DiaSource110)) {\nmsdia_dll = L\"msdia110.dll\";\n} else if (CLSID_DiaSource == _uuidof(DiaSource120)) {\nmsdia_dll = L\"msdia120.dll\";\n} else if (CLSID_DiaSource == _uuidof(DiaSource140)) {\nmsdia_dll = L\"msdia140.dll\";\n}\n```\n\nindicate that the error above is caused by the missing `msdia140.dll` (deduced by matching the `E6756135-1E65-4D17...` from the error line to the source code).\n\nThe solution is to find `msdia140.dll` in your system (simply search for it in `C:`, if not present then download the appropriate VisualStudio redistributables) and copy it to `C:\\Program Files\\Common Files\\Microsoft Shared\\VC` directory. Then open a command line instance with administrator rights and run the command:\n\n```cmd\nC:\\Windows\\system32\\regsvr32 \"C:\\Program Files\\Common Files\\Microsoft Shared\\VC\\msdia140.dll\"\n```\n\nAfter this, `dump_syms.exe` should work properly.\n\n---\n\n## Visual Studio Analysis (Windows)\n\nOpen the *Visual Studio* project with the *exact* source code version used to create the binary and build to create the relevant debug symbols. Then go to `File -\u003e Open -\u003e File...` and open the dump file. A window inside Visual Studio displays the dump file summary info. \n\n![alt text](./doc/01.jpg)\n\nNormally if the `Debug with Native Only` on the right side of the windows is clicked, a debugging session should start, but must likely a *No compatible code running* error will appear. \n\n![alt text](./doc/02.jpg)\n\nTo fix this, it is necessary to reproduce the full environment in which the application crashed. Note the window displaying the dump file info shows the modules involved in the crash including:\n\n```\nC:\\Users\\User\\Desktop\\test\\test.exe\n\n// other modules...\n\nC:\\Users\\User\\Desktop\\test\\Qt5Core.dll\n\n// other modules...\n```\n\nThis is the location in the *Deployment* machine where the crash occured, but this location does not exist yet in the *Development* machine. So after deploying **the exact same version of the application, in the same location**, now is possible to click the `Debug with Native Only` on the right side of the windows, and then the debugger should show the crash line, call stack and other debug information.\n\n![alt text](./doc/03.jpg)\n\n---\n\n## QtCreator Analysis (Linux)\n\nFirst make sure the `PATH` includes `${PWD}/deps/breakpad.git/src/tools/linux/md2core`, then convert the dump file into a core file using breakpad's `minidump-2-core` tool:\n\n```bash\nminidump-2-core test.dmp \u003e test.core\n```\n\nOpen the *QtCreator* project with the *exact* source code version used to create the binary and build to create the relevant debug binary files. \n\nGo to `Debug -\u003e Start Debugging -\u003e Load Core File...`. Then select the core file and the compiled binary and click `OK`. \n\nNormally the debugger should show the crash line, call stack and other debug information.\n\n![alt text](./doc/04.jpg)\n\nIf the application uses shared libraries though, the full call stack might not me shown correctly. One must pay attention to the `Application Output` messages;\n\n```\nDebugging starts\nCould not load shared library symbols for XXX libraries, e.g. ...\n```\n\nThis means it is necessary to tell the debugger where are the shared libraries used by the application. To to this go to `Tools -\u003e Options...` change to the `GDB` tab and in the `Additional Starup Commands` add a line similar to:\n\n```\nset solib-search-path /path/to/the/shared/libs\n```\n\nThen restart the debugging session.\n\n---\n\n## Debbugging symbols on Linux\n\nOn Windows, debugging symbols are separated automatically from the binary files (`*.exe` or `*.dll`) into `*.pdb` files. This reduces the size of the binary files to be deployed. \n\nOn Linux, this has to be done manually, the resulting binaries are too large because they contain all the debug information. To separate them, use the following commands:\n\n```bash\nobjcopy --only-keep-debug \"${binary_file}\" \"${debug_symbols_file}\"\nstrip --strip-debug --strip-unneeded \"${binary_file}\"\nobjcopy --add-gnu-debuglink=\"${debug_symbols_file}\" \"${binary_file}\"\n```\n\nThis will make the binary file much smaller for deployment, while the  debug symbols file can be kept in the *Development* machine for crash analysis. Note the two files are *linked* together (via checsums and file name mechanisms) through the last command of the snippet above.\n\nIn the test project, the symbols separation is done automatically after building the application by the [`qpostprocess.pri` file](./src/qpostprocess.pri).\n\n---\n\n## Sources\n\nThe original wiki for using google's breakpad was taken from [here](https://github.com/JPNaude/dev_notes/wiki/Using-Google-Breakpad-with-Qt).\n\nThe breakpad source code cane be cloned from [here](https://chromium.googlesource.com/breakpad/breakpad/) or [here](https://github.com/google/breakpad.git).\n\nFor **Linux** the breakpad library requires the `linux_syscall_support.h` file which can be obtained from [here](https://chromium.googlesource.com/linux-syscall-support).\n\n---\n\n## References\n\n* 1. \u003chttps://github.com/JPNaude/dev_notes/wiki/Using-Google-Breakpad-with-Qt\u003e\n\n* 2. \u003chttp://www.chromium.org/developers/decoding-crash-dumps\u003e\n\n* 3. \u003chttps://msdn.microsoft.com/en-us/library/fsk896zz.aspx\u003e\n\n* 4. \u003chttps://docs.microsoft.com/en-us/visualstudio/debugger/using-dump-files?view=vs-2019\u003e\n\n* 5. \u003chttps://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_a_minidump\u003e\n\n* 6. \u003chttps://stackoverflow.com/questions/6993061/build-qt-in-release-with-debug-info-mode/35704181#35704181\u003e\n\n* 7. \u003chttps://developer.mozilla.org/en-US/docs/Mozilla/Debugging/Debugging_a_minidump#Using_minidump-2-core_on_Linux\u003e\n\n* 8. \u003chttps://doc.qt.io/qtcreator/creator-debugger-operating-modes.html#launching-in-core-mode\u003e\n\n* 9. \u003chttps://stackoverflow.com/questions/866721/how-to-generate-gcc-debug-symbol-outside-the-build-target\u003e\n\n* 10. \u003chttps://www.computerhope.com/unix/strip.htm\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuangburgos%2Fqcrashhandler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjuangburgos%2Fqcrashhandler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuangburgos%2Fqcrashhandler/lists"}