mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-22 04:46:11 +00:00
Add crash handling system using Breakpad (#1439)
This commit is contained in:
parent
b6406e6ac6
commit
1cb314d674
@ -45,10 +45,11 @@ install:
|
|||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
- cmd: git submodule update --init
|
- cmd: git submodule update --init
|
||||||
|
- scripts\prepare_breakpad.bat
|
||||||
|
|
||||||
# Build config
|
# Build config
|
||||||
build_script:
|
build_script:
|
||||||
- cmd: if defined QMAKE ( call prepare_r2.bat && call build.bat CUTTER_APPVEYOR_R2DEC=true CUTTER_ENABLE_PYTHON=true CUTTER_ENABLE_PYTHON_BINDINGS=true SHIBOKEN_EXECUTABLE="%CUTTER_DEPS_DIR%\pyside\bin\shiboken2.exe" SHIBOKEN_INCLUDEDIR="%CUTTER_DEPS_DIR%/pyside/include/shiboken2" SHIBOKEN_LIBRARY="%CUTTER_DEPS_DIR%/pyside/lib/shiboken2.lib" PYSIDE_INCLUDEDIR="%CUTTER_DEPS_DIR%/pyside/include/PySide2" PYSIDE_LIBRARY="%CUTTER_DEPS_DIR%/pyside/lib/pyside2.lib" PYSIDE_TYPESYSTEMS="%CUTTER_DEPS_DIR%/pyside/share/PySide2/typesystems")
|
- cmd: if defined QMAKE ( call prepare_r2.bat && call build.bat CUTTER_APPVEYOR_R2DEC=true CUTTER_ENABLE_CRASH_REPORTS=true CUTTER_ENABLE_PYTHON=true CUTTER_ENABLE_PYTHON_BINDINGS=true SHIBOKEN_EXECUTABLE="%CUTTER_DEPS_DIR%\pyside\bin\shiboken2.exe" SHIBOKEN_INCLUDEDIR="%CUTTER_DEPS_DIR%/pyside/include/shiboken2" SHIBOKEN_LIBRARY="%CUTTER_DEPS_DIR%/pyside/lib/shiboken2.lib" PYSIDE_INCLUDEDIR="%CUTTER_DEPS_DIR%/pyside/include/PySide2" PYSIDE_LIBRARY="%CUTTER_DEPS_DIR%/pyside/lib/pyside2.lib" PYSIDE_TYPESYSTEMS="%CUTTER_DEPS_DIR%/pyside/share/PySide2/typesystems")
|
||||||
- cmd: if defined MESON ( python meson.py --release --dist=%ARTIFACT_PATH% --backend=%BACKEND% --python )
|
- cmd: if defined MESON ( python meson.py --release --dist=%ARTIFACT_PATH% --backend=%BACKEND% --python )
|
||||||
|
|
||||||
after_build:
|
after_build:
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -71,3 +71,5 @@ compile_commands.json
|
|||||||
|
|
||||||
# cutter-deps
|
# cutter-deps
|
||||||
/cutter-deps
|
/cutter-deps
|
||||||
|
|
||||||
|
/breakpad
|
||||||
|
18
.travis.yml
18
.travis.yml
@ -68,8 +68,14 @@ addons:
|
|||||||
install:
|
install:
|
||||||
- scripts/fetch_deps.sh
|
- scripts/fetch_deps.sh
|
||||||
- source cutter-deps/env.sh
|
- source cutter-deps/env.sh
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH=/usr/local/opt/llvm/bin:$PATH; fi
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export LD_LIBRARY_PATH="`llvm-config --libdir`:$LD_LIBRARY_PATH"; fi
|
export PATH=/usr/local/opt/llvm/bin:$PATH;
|
||||||
|
source scripts/prepare_breakpad_macos.sh;
|
||||||
|
fi
|
||||||
|
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||||
|
export LD_LIBRARY_PATH="`llvm-config --libdir`:$LD_LIBRARY_PATH";
|
||||||
|
source scripts/prepare_breakpad_linux.sh;
|
||||||
|
fi
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- git submodule init ; git submodule update
|
- git submodule init ; git submodule update
|
||||||
@ -84,11 +90,13 @@ before_script:
|
|||||||
script:
|
script:
|
||||||
- mkdir build
|
- mkdir build
|
||||||
- cd build
|
- cd build
|
||||||
|
- export PKG_CONFIG_PATH="$CUSTOM_BREAKPAD_PREFIX/lib/pkgconfig:$CUSTOM_PYTHON_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||||
if [[ "$BUILD_SYSTEM" == "qmake" ]]; then
|
if [[ "$BUILD_SYSTEM" == "qmake" ]]; then
|
||||||
qmake
|
qmake
|
||||||
CUTTER_ENABLE_PYTHON=true
|
CUTTER_ENABLE_PYTHON=true
|
||||||
CUTTER_ENABLE_PYTHON_BINDINGS=true
|
CUTTER_ENABLE_PYTHON_BINDINGS=true
|
||||||
|
CUTTER_ENABLE_CRASH_REPORTS=true
|
||||||
PREFIX=/usr
|
PREFIX=/usr
|
||||||
APPIMAGE=1
|
APPIMAGE=1
|
||||||
../src &&
|
../src &&
|
||||||
@ -101,6 +109,7 @@ script:
|
|||||||
-DPYTHON_EXECUTABLE="$CUTTER_DEPS_PYTHON_PREFIX/bin/python3"
|
-DPYTHON_EXECUTABLE="$CUTTER_DEPS_PYTHON_PREFIX/bin/python3"
|
||||||
-DCUTTER_ENABLE_PYTHON=ON
|
-DCUTTER_ENABLE_PYTHON=ON
|
||||||
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON
|
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON
|
||||||
|
-DCUTTER_ENABLE_CRASH_REPORTS=ON
|
||||||
../src &&
|
../src &&
|
||||||
make -j4;
|
make -j4;
|
||||||
fi
|
fi
|
||||||
@ -110,7 +119,9 @@ script:
|
|||||||
CUTTER_ENABLE_PYTHON=true
|
CUTTER_ENABLE_PYTHON=true
|
||||||
CUTTER_ENABLE_PYTHON_BINDINGS=true
|
CUTTER_ENABLE_PYTHON_BINDINGS=true
|
||||||
CUTTER_BUNDLE_R2_APPBUNDLE=true
|
CUTTER_BUNDLE_R2_APPBUNDLE=true
|
||||||
|
CUTTER_ENABLE_CRASH_REPORTS=true
|
||||||
PYTHON_FRAMEWORK_DIR=$CUTTER_DEPS_PYTHON_FRAMEWORK_DIR
|
PYTHON_FRAMEWORK_DIR=$CUTTER_DEPS_PYTHON_FRAMEWORK_DIR
|
||||||
|
BREAKPAD_FRAMEWORK_DIR=$BREAKPAD_FRAMEWORK_DIR
|
||||||
../src &&
|
../src &&
|
||||||
make -j4;
|
make -j4;
|
||||||
elif [[ "$BUILD_SYSTEM" == "cmake" ]]; then
|
elif [[ "$BUILD_SYSTEM" == "cmake" ]]; then
|
||||||
@ -121,6 +132,8 @@ script:
|
|||||||
-DPYTHON_EXECUTABLE="$CUTTER_DEPS_PYTHON_PREFIX/bin/python3"
|
-DPYTHON_EXECUTABLE="$CUTTER_DEPS_PYTHON_PREFIX/bin/python3"
|
||||||
-DCUTTER_ENABLE_PYTHON=ON
|
-DCUTTER_ENABLE_PYTHON=ON
|
||||||
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON
|
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON
|
||||||
|
-DCUTTER_ENABLE_CRASH_REPORTS=ON
|
||||||
|
-DBREAKPAD_FRAMEWORK_DIR="$BREAKPAD_FRAMEWORK_DIR"
|
||||||
../src &&
|
../src &&
|
||||||
make -j4;
|
make -j4;
|
||||||
fi
|
fi
|
||||||
@ -135,6 +148,7 @@ after_success:
|
|||||||
macdeployqt Cutter.app -executable=Cutter.app/Contents/MacOS/Cutter -libpath="../Frameworks" &&
|
macdeployqt Cutter.app -executable=Cutter.app/Contents/MacOS/Cutter -libpath="../Frameworks" &&
|
||||||
macdeployqt Cutter.app -executable=Cutter.app/Contents/MacOS/Cutter -libpath="../Frameworks" &&
|
macdeployqt Cutter.app -executable=Cutter.app/Contents/MacOS/Cutter -libpath="../Frameworks" &&
|
||||||
cp -a "$QTDIR/lib/QtDBus.framework" "$QTDIR/lib/QtPrintSupport.framework" Cutter.app/Contents/Frameworks &&
|
cp -a "$QTDIR/lib/QtDBus.framework" "$QTDIR/lib/QtPrintSupport.framework" Cutter.app/Contents/Frameworks &&
|
||||||
|
cp -a "$BREAKPAD_FRAMEWORK_DIR/Breakpad.framework" Cutter.app/Contents/Frameworks &&
|
||||||
"$TRAVIS_BUILD_DIR/scripts/appbundle_embed_python.sh" "$CUTTER_DEPS_PYTHON_FRAMEWORK_DIR/Python.framework" Cutter.app Cutter.app/Contents/MacOS/Cutter &&
|
"$TRAVIS_BUILD_DIR/scripts/appbundle_embed_python.sh" "$CUTTER_DEPS_PYTHON_FRAMEWORK_DIR/Python.framework" Cutter.app Cutter.app/Contents/MacOS/Cutter &&
|
||||||
mv Cutter.app/Contents/MacOS/Cutter Cutter.app/Contents/MacOS/Cutter.bin &&
|
mv Cutter.app/Contents/MacOS/Cutter Cutter.app/Contents/MacOS/Cutter.bin &&
|
||||||
cp ../src/macos/Cutter.sh Cutter.app/Contents/MacOS/Cutter &&
|
cp ../src/macos/Cutter.sh Cutter.app/Contents/MacOS/Cutter &&
|
||||||
|
10
build.bat
10
build.bat
@ -1,5 +1,6 @@
|
|||||||
@ECHO off
|
@ECHO off
|
||||||
SETLOCAL ENABLEDELAYEDEXPANSION
|
SETLOCAL ENABLEDELAYEDEXPANSION
|
||||||
|
SETLOCAL ENABLEEXTENSIONS
|
||||||
|
|
||||||
IF "%VisualStudioVersion%" == "14.0" ( IF NOT DEFINED Platform SET "Platform=X86" )
|
IF "%VisualStudioVersion%" == "14.0" ( IF NOT DEFINED Platform SET "Platform=X86" )
|
||||||
FOR /F %%i IN ('powershell -c "\"%Platform%\".toLower()"') DO SET PLATFORM=%%i
|
FOR /F %%i IN ('powershell -c "\"%Platform%\".toLower()"') DO SET PLATFORM=%%i
|
||||||
@ -11,6 +12,7 @@ IF !ERRORLEVEL! NEQ 0 (
|
|||||||
|
|
||||||
SET "R2DIST=r2_dist_%PLATFORM%"
|
SET "R2DIST=r2_dist_%PLATFORM%"
|
||||||
SET "BUILDDIR=build_%PLATFORM%"
|
SET "BUILDDIR=build_%PLATFORM%"
|
||||||
|
SET "BREAKPAD_SOURCE_DIR=%CD%\src\breakpad\src\src"
|
||||||
|
|
||||||
ECHO Preparing directory
|
ECHO Preparing directory
|
||||||
RMDIR /S /Q %BUILDDIR%
|
RMDIR /S /Q %BUILDDIR%
|
||||||
@ -21,8 +23,12 @@ FOR %%i in (src\translations\*.ts) DO lrelease %%i
|
|||||||
|
|
||||||
CD %BUILDDIR%
|
CD %BUILDDIR%
|
||||||
|
|
||||||
|
IF NOT DEFINED CUTTER_ENABLE_CRASH_REPORTS (
|
||||||
|
SET "CUTTER_ENABLE_CRASH_REPORTS=false"
|
||||||
|
)
|
||||||
|
|
||||||
ECHO Building cutter
|
ECHO Building cutter
|
||||||
qmake %* ..\src\cutter.pro -config release
|
qmake BREAKPAD_SOURCE_DIR=%BREAKPAD_SOURCE_DIR% CUTTER_ENABLE_CRASH_REPORTS=%CUTTER_ENABLE_CRASH_REPORTS% %* ..\src\cutter.pro -config release
|
||||||
IF !ERRORLEVEL! NEQ 0 EXIT /B 1
|
IF !ERRORLEVEL! NEQ 0 EXIT /B 1
|
||||||
nmake
|
nmake
|
||||||
IF !ERRORLEVEL! NEQ 0 EXIT /B 1
|
IF !ERRORLEVEL! NEQ 0 EXIT /B 1
|
||||||
@ -34,3 +40,5 @@ XCOPY /S /I ..\%R2DIST%\radare2 cutter\radare2
|
|||||||
COPY ..\%R2DIST%\*.dll cutter\
|
COPY ..\%R2DIST%\*.dll cutter\
|
||||||
windeployqt cutter\cutter.exe
|
windeployqt cutter\cutter.exe
|
||||||
FOR %%i in (..\src\translations\*.qm) DO MOVE "%%~fi" cutter\translations
|
FOR %%i in (..\src\translations\*.qm) DO MOVE "%%~fi" cutter\translations
|
||||||
|
|
||||||
|
ENDLOCAL
|
||||||
|
13
build.sh
13
build.sh
@ -6,7 +6,7 @@
|
|||||||
ERR=0
|
ERR=0
|
||||||
|
|
||||||
#### User variables ####
|
#### User variables ####
|
||||||
BUILD="build"
|
BUILD="`pwd`/build"
|
||||||
QMAKE_CONF=""
|
QMAKE_CONF=""
|
||||||
ROOT_DIR=`pwd`
|
ROOT_DIR=`pwd`
|
||||||
|
|
||||||
@ -63,6 +63,16 @@ find_gmake() {
|
|||||||
echo "$gmakepath"
|
echo "$gmakepath"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prepare_breakpad() {
|
||||||
|
if [[ $OSTYPE == "linux-gnu" ]]; then
|
||||||
|
source $ROOT_DIR/scripts/prepare_breakpad_linux.sh
|
||||||
|
export PKG_CONFIG_PATH="$CUSTOM_BREAKPAD_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
elif [[ $OSTYPE == "darwin" ]]; then
|
||||||
|
source $ROOT_DIR/scripts/prepare_breakpad_macos.sh
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
# Build radare2
|
# Build radare2
|
||||||
check_r2
|
check_r2
|
||||||
if [ $? -eq 1 ]; then
|
if [ $? -eq 1 ]; then
|
||||||
@ -86,6 +96,7 @@ fi
|
|||||||
$(find_lrelease) ./src/Cutter.pro
|
$(find_lrelease) ./src/Cutter.pro
|
||||||
|
|
||||||
# Build
|
# Build
|
||||||
|
prepare_breakpad
|
||||||
mkdir -p "$BUILD"
|
mkdir -p "$BUILD"
|
||||||
cd "$BUILD" || exit 1
|
cd "$BUILD" || exit 1
|
||||||
$(find_qmake) ../src/Cutter.pro $QMAKE_CONF
|
$(find_qmake) ../src/Cutter.pro $QMAKE_CONF
|
||||||
|
@ -11,9 +11,11 @@ The “official” way to build Cutter is by using qmake, but there are two
|
|||||||
alternatives – cmake and meson.
|
alternatives – cmake and meson.
|
||||||
|
|
||||||
In any case, there are obviously some requirements:
|
In any case, there are obviously some requirements:
|
||||||
- Radare2 installed from submodule
|
|
||||||
- Qt 5.9 or above
|
* Radare2 installed from submodule
|
||||||
- Python3.6
|
* Qt 5.9 or above
|
||||||
|
* Python3.6
|
||||||
|
* Breakpad installed using script (optional, disabled by default)
|
||||||
|
|
||||||
Before compiling, note that we also provide binaries available for
|
Before compiling, note that we also provide binaries available for
|
||||||
windows/linux/MacOS `here <https://github.com/radareorg/cutter/releases>`_.
|
windows/linux/MacOS `here <https://github.com/radareorg/cutter/releases>`_.
|
||||||
@ -23,9 +25,33 @@ windows/linux/MacOS `here <https://github.com/radareorg/cutter/releases>`_.
|
|||||||
Building options
|
Building options
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Note that there are two major building options available:
|
Note that there are three major building options available:
|
||||||
- ``CUTTER_ENABLE_PYTHON`` compile with Python support
|
|
||||||
- ``CUTTER_ENABLE_PYTHON_BINDINGS`` automatically generate Python Bindings with Shiboken2, required for Python plugins!
|
* ``CUTTER_ENABLE_PYTHON`` compile with Python support
|
||||||
|
* ``CUTTER_ENABLE_PYTHON_BINDINGS`` automatically generate Python Bindings with Shiboken2, required for Python plugins!
|
||||||
|
* ``CUTTER_ENABLE_CRASH_REPORTS`` is used to compile Cutter with crash handling system enabled (Breakpad)
|
||||||
|
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Preparing Breakpad
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
If you want to build Cutter with crash handling system, you want prepare Breakpad before.
|
||||||
|
For this simply run one of the scripts (according to your OS) from root Cutter directory:
|
||||||
|
|
||||||
|
.. code:: sh
|
||||||
|
|
||||||
|
source scripts/prepare_breakpad_linux.sh # Linux
|
||||||
|
source scripts/prepare_breakpad_macos.sh # MacOS
|
||||||
|
scripts/prepare_breakpad.bat # Windows
|
||||||
|
|
||||||
|
Then if you are building on Linux you want to change ``PKG_CONFIG_PATH`` environment variable
|
||||||
|
so it contains ``$CUSTOM_BREAKPAD_PREFIX/lib/pkgconfig``. For this simply run
|
||||||
|
|
||||||
|
.. code:: sh
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$CUSTOM_BREAKPAD_PREFIX/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
|
|
||||||
|
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
@ -73,12 +99,12 @@ Building on Linux
|
|||||||
The root for CMake is in src/. In-source builds are **not allowed**, so
|
The root for CMake is in src/. In-source builds are **not allowed**, so
|
||||||
you **must** run CMake from a separate directory:
|
you **must** run CMake from a separate directory:
|
||||||
|
|
||||||
::
|
.. code:: sh
|
||||||
|
|
||||||
cd src
|
cd src
|
||||||
mkdir build
|
mkdir build
|
||||||
cd build
|
cd build
|
||||||
cmake ..
|
cmake .. # Don't forget to provide build options
|
||||||
|
|
||||||
If all went well, you should now have a working Makefile in your build
|
If all went well, you should now have a working Makefile in your build
|
||||||
directory:
|
directory:
|
||||||
|
32
docs/source/crash-handling-system.rst
Normal file
32
docs/source/crash-handling-system.rst
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
Crash Handling System
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Cutter uses `Breakpad <https://github.com/google/breakpad>`__ as backend
|
||||||
|
for crash handling.
|
||||||
|
|
||||||
|
Crash Handling System is disabled by default to do not interfere developers from debugging.
|
||||||
|
To enable this system there is building option ``CUTTER_ENABLE_CRASH_REPORTS``.
|
||||||
|
|
||||||
|
Solution description
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
There are only 2 source files:
|
||||||
|
|
||||||
|
* ``CrashHandler.h``
|
||||||
|
* ``CrashHandler.cpp``
|
||||||
|
|
||||||
|
And API is very simple: only one function - ``initCrashHandler()`` that enables Crash Handling System if
|
||||||
|
``CUTTER_ENABLE_CRASH_REPORTS`` is true, otherwise does nothing.
|
||||||
|
|
||||||
|
As soon as signal is raised ``crashHandler(int signum)`` is called with signal's code as argument.
|
||||||
|
This function first of all writes crash dump to OS's Temp directory to catch core and memory state
|
||||||
|
as it was at the crash moment.
|
||||||
|
|
||||||
|
Then crash dialog is shown:
|
||||||
|
|
||||||
|
.. image :: images/crash-dialog.png
|
||||||
|
|
||||||
|
If user chose to create crash dump, prepared dump is moved to directory specified by user.
|
||||||
|
And then success dialog is shown:
|
||||||
|
|
||||||
|
.. image :: images/success-dump-dialog.png
|
BIN
docs/source/images/crash-dialog.png
Normal file
BIN
docs/source/images/crash-dialog.png
Normal file
Binary file not shown.
After (image error) Size: 29 KiB |
BIN
docs/source/images/success-dump-dialog.png
Normal file
BIN
docs/source/images/success-dump-dialog.png
Normal file
Binary file not shown.
After (image error) Size: 14 KiB |
34
scripts/breakpad_client.gyp
Normal file
34
scripts/breakpad_client.gyp
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
'includes': [
|
||||||
|
'../../build/common.gypi'
|
||||||
|
],
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'build_all',
|
||||||
|
'type': 'none',
|
||||||
|
'dependencies': [
|
||||||
|
'./crash_generation/crash_generation.gyp:*',
|
||||||
|
'./handler/exception_handler.gyp:*',
|
||||||
|
'./sender/crash_report_sender.gyp:*',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'target_name': 'common',
|
||||||
|
'type': 'static_library',
|
||||||
|
'include_dirs': [
|
||||||
|
'<(DEPTH)',
|
||||||
|
],
|
||||||
|
'direct_dependent_settings': {
|
||||||
|
'include_dirs': [
|
||||||
|
'<(DEPTH)',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'sources': [
|
||||||
|
'<(DEPTH)/common/windows/guid_string.cc',
|
||||||
|
'<(DEPTH)/common/windows/guid_string.h',
|
||||||
|
'<(DEPTH)/common/windows/http_upload.h',
|
||||||
|
'<(DEPTH)/common/windows/string_utils.cc',
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
1377
scripts/breakpad_macos.patch
Normal file
1377
scripts/breakpad_macos.patch
Normal file
File diff suppressed because it is too large
Load Diff
17
scripts/dump_syms.gyp
Normal file
17
scripts/dump_syms.gyp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
'includes': [
|
||||||
|
'../../../build/common.gypi',
|
||||||
|
],
|
||||||
|
'targets': [
|
||||||
|
{
|
||||||
|
'target_name': 'dump_syms',
|
||||||
|
'type': 'executable',
|
||||||
|
'sources': [
|
||||||
|
'dump_syms.cc',
|
||||||
|
],
|
||||||
|
'dependencies': [
|
||||||
|
'../../../common/windows/common_windows.gyp:common_windows_lib',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
29
scripts/prepare_breakpad.bat
Normal file
29
scripts/prepare_breakpad.bat
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
@ECHO OFF
|
||||||
|
SET ROOT_DIR=%CD%
|
||||||
|
|
||||||
|
powershell -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; wget https://storage.googleapis.com/chrome-infra/depot_tools.zip -OutFile depot_tools.zip "
|
||||||
|
7z -bd x %ROOT_DIR%\depot_tools.zip -odepot_tools
|
||||||
|
powershell -Command "depot_tools\update_depot_tools"
|
||||||
|
SET BUFF_PATH=%PATH%
|
||||||
|
SET DEPOT_TOOLS=%ROOT_DIR%\depot_tools
|
||||||
|
set PATH=%DEPOT_TOOLS%;%BUFF_PATH%
|
||||||
|
|
||||||
|
mkdir %ROOT_DIR%\src\breakpad
|
||||||
|
CD %ROOT_DIR%\src\breakpad
|
||||||
|
powershell -Command "fetch breakpad"
|
||||||
|
powershell -Command "gclient sync"
|
||||||
|
|
||||||
|
CD %ROOT_DIR%\src\breakpad\src\src\client\windows
|
||||||
|
DEL %CD%\breakpad_client.gyp
|
||||||
|
DEL %CD%\breakpad_client.sln
|
||||||
|
DEL %CD%\common.vcxproj
|
||||||
|
DEL %CD%\common.vcxproj.filters
|
||||||
|
DEL %CD%\build_all.vcxproj
|
||||||
|
COPY %ROOT_DIR%\scripts\breakpad_client.gyp %CD%
|
||||||
|
|
||||||
|
CD %ROOT_DIR%\src\breakpad\src\src
|
||||||
|
powershell -Command "tools\gyp\gyp.bat --no-circular-check client\windows\breakpad_client.gyp -Dwin_release_RuntimeLibrary=2 -Dwin_debug_RuntimeLibrary=2 -Dplatform=%ARCH% -Dconfiguration=release"
|
||||||
|
|
||||||
|
set PATH=%BUFF_PATH%
|
||||||
|
msbuild /m %CD%\client\windows\breakpad_client.sln /p:Configuration=release /p:Platform=%ARCH%
|
||||||
|
CD %ROOT_DIR%
|
9
scripts/prepare_breakpad_linux.sh
Executable file
9
scripts/prepare_breakpad_linux.sh
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
git clone https://github.com/google/breakpad.git
|
||||||
|
cd breakpad
|
||||||
|
git clone https://chromium.googlesource.com/linux-syscall-support src/third_party/lss
|
||||||
|
CFLAGS=-w CXXFLAGS=-w ./configure --prefix=`pwd`/prefix && make -j4 && make install || exit 1
|
||||||
|
|
||||||
|
export CUSTOM_BREAKPAD_PREFIX="`pwd`/prefix"
|
||||||
|
cd ..
|
22
scripts/prepare_breakpad_macos.sh
Executable file
22
scripts/prepare_breakpad_macos.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SCRIPTPATH=$(realpath "$(dirname "${BASH_SOURCE[0]}")")
|
||||||
|
|
||||||
|
DIR="$SCRIPTPATH/.."
|
||||||
|
cd "$DIR" || exit 1
|
||||||
|
BREAKPAD_FRAMEWORK_DIR="$DIR/breakpad/framework"
|
||||||
|
BREAKPAD_DUMP_SYMS_DIR="$DIR/breakpad/bin"
|
||||||
|
git clone https://github.com/google/breakpad.git || exit 1
|
||||||
|
mkdir $BREAKPAD_FRAMEWORK_DIR
|
||||||
|
mkdir $BREAKPAD_DUMP_SYMS_DIR
|
||||||
|
cd breakpad || exit 1
|
||||||
|
git checkout 4d550cceca107f36c4bc1ea1126b7d32cc50f424 || exit 1
|
||||||
|
git apply "$SCRIPTPATH/breakpad_macos.patch" || exit 1
|
||||||
|
cd src/client/mac/ && xcodebuild -sdk macosx || exit 1
|
||||||
|
cp -R build/Release/Breakpad.framework "$BREAKPAD_FRAMEWORK_DIR" || exit 1
|
||||||
|
|
||||||
|
cd $DIR/breakpad || exit 1
|
||||||
|
cp -R src/. framework/Breakpad.framework/Headers || exit 1
|
||||||
|
|
||||||
|
export BREAKPAD_FRAMEWORK_DIR=$BREAKPAD_FRAMEWORK_DIR
|
||||||
|
cd $DIR
|
@ -10,6 +10,7 @@ set(CUTTER_PYTHON_MIN 3.5)
|
|||||||
|
|
||||||
option(CUTTER_ENABLE_PYTHON "Enable Python integration. Requires Python >= ${CUTTER_PYTHON_MIN}." OFF)
|
option(CUTTER_ENABLE_PYTHON "Enable Python integration. Requires Python >= ${CUTTER_PYTHON_MIN}." OFF)
|
||||||
option(CUTTER_ENABLE_PYTHON_BINDINGS "Enable generating Python bindings with Shiboken2. Unused if CUTTER_ENABLE_PYTHON=OFF." OFF)
|
option(CUTTER_ENABLE_PYTHON_BINDINGS "Enable generating Python bindings with Shiboken2. Unused if CUTTER_ENABLE_PYTHON=OFF." OFF)
|
||||||
|
option(CUTTER_ENABLE_CRASH_REPORTS "Enable crash report system. Unused if CUTTER_ENABLE_CRASH_REPORTS=OFF" OFF)
|
||||||
|
|
||||||
if(NOT CUTTER_ENABLE_PYTHON)
|
if(NOT CUTTER_ENABLE_PYTHON)
|
||||||
set(CUTTER_ENABLE_PYTHON_BINDINGS OFF)
|
set(CUTTER_ENABLE_PYTHON_BINDINGS OFF)
|
||||||
@ -93,6 +94,7 @@ message(STATUS "Building Cutter version ${CUTTER_VERSION_FULL}")
|
|||||||
message(STATUS "Options:")
|
message(STATUS "Options:")
|
||||||
message(STATUS "- Python: ${CUTTER_ENABLE_PYTHON}")
|
message(STATUS "- Python: ${CUTTER_ENABLE_PYTHON}")
|
||||||
message(STATUS "- Python Bindings: ${CUTTER_ENABLE_PYTHON_BINDINGS}")
|
message(STATUS "- Python Bindings: ${CUTTER_ENABLE_PYTHON_BINDINGS}")
|
||||||
|
message(STATUS "- Crash Handling: ${CUTTER_ENABLE_CRASH_REPORTS}")
|
||||||
message(STATUS "")
|
message(STATUS "")
|
||||||
|
|
||||||
|
|
||||||
@ -134,6 +136,24 @@ endif()
|
|||||||
add_executable(Cutter MACOSX_BUNDLE ${UI_FILES} ${QRC_FILES} ${SOURCE_FILES} ${HEADER_FILES} ${BINDINGS_SOURCE})
|
add_executable(Cutter MACOSX_BUNDLE ${UI_FILES} ${QRC_FILES} ${SOURCE_FILES} ${HEADER_FILES} ${BINDINGS_SOURCE})
|
||||||
set_target_properties(Cutter PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist")
|
set_target_properties(Cutter PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist")
|
||||||
|
|
||||||
|
if(CUTTER_ENABLE_CRASH_REPORTS)
|
||||||
|
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
target_link_libraries(Cutter Threads::Threads)
|
||||||
|
|
||||||
|
add_definitions(-DCUTTER_ENABLE_CRASH_REPORTS)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g ")
|
||||||
|
if(DEFINED BREAKPAD_FRAMEWORK_DIR)
|
||||||
|
include_directories("${BREAKPAD_FRAMEWORK_DIR}/Breakpad.framework/Headers")
|
||||||
|
set_target_properties(Cutter PROPERTIES LINK_FLAGS "-Wl,-F${BREAKPAD_FRAMEWORK_DIR}")
|
||||||
|
target_link_libraries(Cutter "-framework Breakpad")
|
||||||
|
else()
|
||||||
|
find_package(Breakpad REQUIRED)
|
||||||
|
include_directories(${BREAKPAD_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(Cutter ${BREAKPAD_LINK_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(Cutter Qt5::Core Qt5::Widgets Qt5::Gui Qt5::Svg Qt5::Network)
|
target_link_libraries(Cutter Qt5::Core Qt5::Widgets Qt5::Gui Qt5::Svg Qt5::Network)
|
||||||
target_link_libraries(Cutter ${RADARE2_LIBRARIES})
|
target_link_libraries(Cutter ${RADARE2_LIBRARIES})
|
||||||
if(CUTTER_ENABLE_PYTHON)
|
if(CUTTER_ENABLE_PYTHON)
|
||||||
|
@ -32,6 +32,8 @@ QT += core gui widgets svg network
|
|||||||
QT_CONFIG -= no-pkg-config
|
QT_CONFIG -= no-pkg-config
|
||||||
CONFIG += c++11
|
CONFIG += c++11
|
||||||
|
|
||||||
|
!defined(CUTTER_ENABLE_CRASH_REPORTS, var) CUTTER_ENABLE_CRASH_REPORTS=false
|
||||||
|
equals(CUTTER_ENABLE_CRASH_REPORTS, true) CONFIG += CUTTER_ENABLE_CRASH_REPORTS
|
||||||
!defined(CUTTER_ENABLE_PYTHON, var) CUTTER_ENABLE_PYTHON=false
|
!defined(CUTTER_ENABLE_PYTHON, var) CUTTER_ENABLE_PYTHON=false
|
||||||
equals(CUTTER_ENABLE_PYTHON, true) CONFIG += CUTTER_ENABLE_PYTHON
|
equals(CUTTER_ENABLE_PYTHON, true) CONFIG += CUTTER_ENABLE_PYTHON
|
||||||
|
|
||||||
@ -49,6 +51,13 @@ equals(CUTTER_BUNDLE_R2_APPBUNDLE, true) CONFIG += CUTTER_BUNDLE_R2_APPBU
|
|||||||
!defined(CUTTER_APPVEYOR_R2DEC, var) CUTTER_APPVEYOR_R2DEC=false
|
!defined(CUTTER_APPVEYOR_R2DEC, var) CUTTER_APPVEYOR_R2DEC=false
|
||||||
equals(CUTTER_APPVEYOR_R2DEC, true) CONFIG += CUTTER_APPVEYOR_R2DEC
|
equals(CUTTER_APPVEYOR_R2DEC, true) CONFIG += CUTTER_APPVEYOR_R2DEC
|
||||||
|
|
||||||
|
CUTTER_ENABLE_CRASH_REPORTS {
|
||||||
|
message("Crash report support enabled.")
|
||||||
|
DEFINES += CUTTER_ENABLE_CRASH_REPORTS
|
||||||
|
} else {
|
||||||
|
message("Crash report support disabled.")
|
||||||
|
}
|
||||||
|
|
||||||
CUTTER_ENABLE_PYTHON {
|
CUTTER_ENABLE_PYTHON {
|
||||||
message("Python enabled.")
|
message("Python enabled.")
|
||||||
DEFINES += CUTTER_ENABLE_PYTHON
|
DEFINES += CUTTER_ENABLE_PYTHON
|
||||||
@ -188,6 +197,29 @@ CUTTER_ENABLE_PYTHON {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CUTTER_ENABLE_CRASH_REPORTS {
|
||||||
|
QMAKE_CXXFLAGS += -g
|
||||||
|
defined(BREAKPAD_FRAMEWORK_DIR, var)|defined(BREAKPAD_SOURCE_DIR, var) {
|
||||||
|
defined(BREAKPAD_FRAMEWORK_DIR, var) {
|
||||||
|
INCLUDEPATH += $$BREAKPAD_FRAMEWORK_DIR/Breakpad.framework/Headers
|
||||||
|
LIBS += -F$$BREAKPAD_FRAMEWORK_DIR -framework Breakpad
|
||||||
|
}
|
||||||
|
defined(BREAKPAD_SOURCE_DIR, var) {
|
||||||
|
INCLUDEPATH += $$BREAKPAD_SOURCE_DIR
|
||||||
|
win32 {
|
||||||
|
LIBS += -L$$quote($$BREAKPAD_SOURCE_DIR\\client\\windows\\release\\lib) -lexception_handler -lcrash_report_sender -lcrash_generation_server -lcrash_generation_client -lcommon
|
||||||
|
}
|
||||||
|
unix:LIBS += -L$$BREAKPAD_SOURCE_DIR/client/linux -lbreakpad-client
|
||||||
|
macos:error("Please use scripts\prepare_breakpad_macos.sh script to provide breakpad framework.")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CONFIG += link_pkgconfig
|
||||||
|
!packagesExist(breakpad-client) {
|
||||||
|
error("ERROR: Breakpad could not be found. Make sure it is available to pkg-config.")
|
||||||
|
}
|
||||||
|
PKGCONFIG += breakpad-client
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macx:CUTTER_BUNDLE_R2_APPBUNDLE {
|
macx:CUTTER_BUNDLE_R2_APPBUNDLE {
|
||||||
message("Using r2 rom AppBundle")
|
message("Using r2 rom AppBundle")
|
||||||
@ -310,6 +342,8 @@ SOURCES += \
|
|||||||
dialogs/LinkTypeDialog.cpp \
|
dialogs/LinkTypeDialog.cpp \
|
||||||
common/UpdateWorker.cpp \
|
common/UpdateWorker.cpp \
|
||||||
widgets/MemoryDockWidget.cpp \
|
widgets/MemoryDockWidget.cpp \
|
||||||
|
common/CrashHandler.cpp \
|
||||||
|
common/BugReporting.cpp \
|
||||||
common/HighDpiPixmap.cpp \
|
common/HighDpiPixmap.cpp \
|
||||||
widgets/GraphGridLayout.cpp
|
widgets/GraphGridLayout.cpp
|
||||||
|
|
||||||
@ -421,6 +455,7 @@ HEADERS += \
|
|||||||
common/RunScriptTask.h \
|
common/RunScriptTask.h \
|
||||||
common/Json.h \
|
common/Json.h \
|
||||||
dialogs/EditMethodDialog.h \
|
dialogs/EditMethodDialog.h \
|
||||||
|
common/CrashHandler.h \
|
||||||
dialogs/LoadNewTypesDialog.h \
|
dialogs/LoadNewTypesDialog.h \
|
||||||
widgets/SdbWidget.h \
|
widgets/SdbWidget.h \
|
||||||
common/PythonManager.h \
|
common/PythonManager.h \
|
||||||
@ -429,6 +464,7 @@ HEADERS += \
|
|||||||
common/UpdateWorker.h \
|
common/UpdateWorker.h \
|
||||||
dialogs/LinkTypeDialog.h \
|
dialogs/LinkTypeDialog.h \
|
||||||
widgets/MemoryDockWidget.h \
|
widgets/MemoryDockWidget.h \
|
||||||
|
common/BugReporting.h \
|
||||||
common/HighDpiPixmap.h \
|
common/HighDpiPixmap.h \
|
||||||
widgets/GraphLayout.h \
|
widgets/GraphLayout.h \
|
||||||
widgets/GraphGridLayout.h
|
widgets/GraphGridLayout.h
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "core/MainWindow.h"
|
#include "core/MainWindow.h"
|
||||||
#include "common/UpdateWorker.h"
|
#include "common/UpdateWorker.h"
|
||||||
#include "CutterConfig.h"
|
#include "CutterConfig.h"
|
||||||
|
#include "common/CrashHandler.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Migrate Settings used before Cutter 1.8
|
* @brief Migrate Settings used before Cutter 1.8
|
||||||
@ -20,6 +21,8 @@ static void migrateSettings(QSettings &newSettings)
|
|||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
initCrashHandler();
|
||||||
|
|
||||||
qRegisterMetaType<QList<StringDescription>>();
|
qRegisterMetaType<QList<StringDescription>>();
|
||||||
qRegisterMetaType<QList<FunctionDescription>>();
|
qRegisterMetaType<QList<FunctionDescription>>();
|
||||||
|
|
||||||
|
46
src/cmake/FindBreakpad.cmake
Normal file
46
src/cmake/FindBreakpad.cmake
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# - Find Breakpad
|
||||||
|
#
|
||||||
|
# BREAKPAD_FOUND - True if Breakpad has been found.
|
||||||
|
# BREAKPAD_INCLUDE_DIRS - Breakpad include directory
|
||||||
|
# BREAKPAD_LIBRARIES - List of libraries when using Breakpad.
|
||||||
|
# BREAKPAD_LIBRARY_DIRS - Breakpad library directories
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
find_path(BREAKPAD_INCLUDE_DIRS
|
||||||
|
HINTS
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/prefix/include/breakpad")
|
||||||
|
|
||||||
|
set(BREAKPAD_LIBRARY_NAMES
|
||||||
|
BREAKPAD_CLIENT
|
||||||
|
BREAKPAD)
|
||||||
|
|
||||||
|
set(BREAKPAD_LIBRARIES "")
|
||||||
|
set(BREAKPAD_LIBRARIES_VARS "")
|
||||||
|
foreach(libname ${BREAKPAD_LIBRARY_NAMES})
|
||||||
|
find_library(BREAKPAD_LIBRARY_${libname}
|
||||||
|
${libname}
|
||||||
|
HINTS
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/breakpad/prefix/lib")
|
||||||
|
|
||||||
|
list(APPEND BREAKPAD_LIBRARIES ${BREAKPAD_LIBRARY_${libname}})
|
||||||
|
list(APPEND BREAKPAD_LIBRARIES_VARS "BREAKPAD_LIBRARY_${libname}")
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
set(BREAKPAD_LIBRARY_DIRS "")
|
||||||
|
else()
|
||||||
|
set(BREAKPAD_CMAKE_PREFIX_PATH_TEMP ${CMAKE_PREFIX_PATH})
|
||||||
|
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_CURRENT_SOURCE_DIR}/breakpad/prefix")
|
||||||
|
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_search_module(BREAKPAD REQUIRED breakpad-client)
|
||||||
|
|
||||||
|
# reset CMAKE_PREFIX_PATH
|
||||||
|
set(CMAKE_PREFIX_PATH ${BREAKPAD_CMAKE_PREFIX_PATH_TEMP})
|
||||||
|
mark_as_advanced(BREAKPAD_CMAKE_PREFIX_PATH_TEMP)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(BREAKPAD REQUIRED_VARS BREAKPAD_LIBRARIES BREAKPAD_INCLUDE_DIRS)
|
||||||
|
|
||||||
|
mark_as_advanced(BREAKPAD_LIBRARIES_VARS)
|
||||||
|
|
45
src/common/BugReporting.cpp
Normal file
45
src/common/BugReporting.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include "BugReporting.h"
|
||||||
|
|
||||||
|
#include "Cutter.h"
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include "CutterConfig.h"
|
||||||
|
#include <QDesktopServices>
|
||||||
|
|
||||||
|
void openIssue()
|
||||||
|
{
|
||||||
|
QString url, osInfo, format, arch, type;
|
||||||
|
//Pull in info needed for git issue
|
||||||
|
osInfo = QSysInfo::productType() + " " +
|
||||||
|
(QSysInfo::productVersion() == "unknown"
|
||||||
|
? ""
|
||||||
|
: QSysInfo::productVersion());
|
||||||
|
QJsonDocument docu = Core()->getFileInfo();
|
||||||
|
QJsonObject coreObj = docu.object()["core"].toObject();
|
||||||
|
QJsonObject binObj = docu.object()["bin"].toObject();
|
||||||
|
if (!binObj.QJsonObject::isEmpty()) {
|
||||||
|
format = coreObj["format"].toString();
|
||||||
|
arch = binObj["arch"].toString();
|
||||||
|
if (!binObj["type"].isUndefined()) {
|
||||||
|
type = coreObj["type"].toString();
|
||||||
|
} else {
|
||||||
|
type = "N/A";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
format = coreObj["format"].toString();
|
||||||
|
arch = "N/A";
|
||||||
|
type = "N/A";
|
||||||
|
}
|
||||||
|
url =
|
||||||
|
"https://github.com/radareorg/cutter/issues/new?&body=**Environment information**\n* Operating System: "
|
||||||
|
+ osInfo + "\n* Cutter version: " + CUTTER_VERSION_FULL +
|
||||||
|
"\n* File format: " + format + "\n * Arch: " + arch + "\n * Type: " + type +
|
||||||
|
"\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\n"
|
||||||
|
"Steps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n"
|
||||||
|
"4. See error\n\n**Expected behavior**\n"
|
||||||
|
"A clear and concise description of what you expected to happen.\n\n"
|
||||||
|
"**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n"
|
||||||
|
"**Additional context**\nAdd any other context about the problem here.";
|
||||||
|
|
||||||
|
QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
|
||||||
|
}
|
10
src/common/BugReporting.h
Normal file
10
src/common/BugReporting.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef CRASHREPORTING_H
|
||||||
|
#define CRASHREPORTING_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Opens issue on Cutter's github page
|
||||||
|
* with current file and system information.
|
||||||
|
*/
|
||||||
|
void openIssue();
|
||||||
|
|
||||||
|
#endif // CRASHREPORTING_H
|
229
src/common/CrashHandler.cpp
Normal file
229
src/common/CrashHandler.cpp
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
#include "CrashHandler.h"
|
||||||
|
|
||||||
|
#ifdef CUTTER_ENABLE_CRASH_REPORTS
|
||||||
|
#include "BugReporting.h"
|
||||||
|
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <QString>
|
||||||
|
#include <QTime>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#if defined (Q_OS_LINUX)
|
||||||
|
#include "client/linux/handler/exception_handler.h"
|
||||||
|
#elif defined (Q_OS_WIN32)
|
||||||
|
#include "client/windows/handler/exception_handler.h"
|
||||||
|
#elif defined (Q_OS_MACOS)
|
||||||
|
#include "client/mac/handler/exception_handler.h"
|
||||||
|
#endif // Q_OS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Here will be placed crash dump at the first place
|
||||||
|
// and then moved if needed
|
||||||
|
#if defined (Q_OS_LINUX) || defined (Q_OS_MACOS)
|
||||||
|
static std::string tmpLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation).toStdString();
|
||||||
|
#else
|
||||||
|
static std::wstring tmpLocation = QStandardPaths::writableLocation(QStandardPaths::TempLocation).toStdWString();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const QMap<int, QString> sigNumDescription = {
|
||||||
|
#ifdef SIGSEGV
|
||||||
|
{ SIGSEGV, "SIGSEGV" },
|
||||||
|
#endif // SIGSEGV
|
||||||
|
#ifdef SIGILL
|
||||||
|
{ SIGILL, "SIGILL" },
|
||||||
|
#endif // SIGILL
|
||||||
|
#ifdef SIGFPE
|
||||||
|
{ SIGFPE, "SIGFPE" },
|
||||||
|
#endif // SIGFPE
|
||||||
|
#ifdef SIGABRT
|
||||||
|
{ SIGABRT, "SIGABRT" },
|
||||||
|
#endif // SIGABRT
|
||||||
|
#ifdef SIGBUS
|
||||||
|
{ SIGBUS, "SIGBUS" },
|
||||||
|
#endif // SIGBUS
|
||||||
|
#ifdef SIGPIPE
|
||||||
|
{ SIGPIPE, "SIGPIPE" },
|
||||||
|
#endif // SIGPIPE
|
||||||
|
#ifdef SIGSYS
|
||||||
|
{ SIGSYS, "SIGSYS" }
|
||||||
|
#endif // SIGSYS
|
||||||
|
};
|
||||||
|
|
||||||
|
static QString dumpFileFullPath = "";
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
// Called if crash dump was successfully created
|
||||||
|
// Saves path to file
|
||||||
|
bool callback(const wchar_t *_dump_dir,
|
||||||
|
const wchar_t *_minidump_id,
|
||||||
|
void *context, EXCEPTION_POINTERS *exinfo,
|
||||||
|
MDRawAssertionInfo *assertion,
|
||||||
|
bool success)
|
||||||
|
{
|
||||||
|
QString dir = QString::fromWCharArray(_dump_dir);
|
||||||
|
QString id = QString::fromWCharArray(_minidump_id);
|
||||||
|
dumpFileFullPath = QDir(dir).filePath(id + ".dmp");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#elif defined (Q_OS_LINUX)
|
||||||
|
// Called if crash dump was successfully created
|
||||||
|
// Saves path to file
|
||||||
|
bool callback(const google_breakpad::MinidumpDescriptor &md, void *context, bool b)
|
||||||
|
{
|
||||||
|
dumpFileFullPath = md.path();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#elif defined (Q_OS_MACOS)
|
||||||
|
// Called if crash dump was successfully created
|
||||||
|
// Saves path to file
|
||||||
|
bool callback(const char *dump_dir, const char *minidump_id, void *context, bool succeeded)
|
||||||
|
{
|
||||||
|
QString dir = QString::fromUtf8(dump_dir);
|
||||||
|
QString id = QString::fromUtf8(minidump_id);
|
||||||
|
dumpFileFullPath = QDir(dir).filePath(id + ".dmp");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif // Q_OS
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes minidump and put its name in dumpFileFullPath.
|
||||||
|
* @return true on succes
|
||||||
|
*/
|
||||||
|
bool writeMinidump()
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
#if defined (Q_OS_LINUX) || defined (Q_OS_MACOS)
|
||||||
|
ok = google_breakpad::ExceptionHandler::WriteMinidump(tmpLocation,
|
||||||
|
callback,
|
||||||
|
nullptr);
|
||||||
|
#elif defined (Q_OS_WIN32)
|
||||||
|
ok = google_breakpad::ExceptionHandler::WriteMinidump(tmpLocation,
|
||||||
|
callback,
|
||||||
|
nullptr);
|
||||||
|
#endif // Q_OS
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[noreturn]] void crashHandler(int signum)
|
||||||
|
{
|
||||||
|
// As soon as Cutter crashed, crash dump is created, so core and memory state
|
||||||
|
// is not changed by all stuff with user interation going on below.
|
||||||
|
bool ok = writeMinidump();
|
||||||
|
|
||||||
|
QString err = sigNumDescription.contains(signum) ?
|
||||||
|
sigNumDescription[signum] :
|
||||||
|
QObject::tr("undefined");
|
||||||
|
|
||||||
|
|
||||||
|
QMessageBox mb;
|
||||||
|
mb.setWindowTitle(QObject::tr("Cutter encountered a problem"));
|
||||||
|
mb.setText(QObject::tr("Cutter received a <b>%1</b> it can't handle and will close.<br/>"
|
||||||
|
"Would you like to create a crash dump for bug report?"
|
||||||
|
).arg(err));
|
||||||
|
mb.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||||
|
mb.button(QMessageBox::Yes)->setText(QObject::tr("Create a crash dump"));
|
||||||
|
mb.button(QMessageBox::No)->setText(QObject::tr("Do not report"));
|
||||||
|
mb.setDefaultButton(QMessageBox::Yes);
|
||||||
|
|
||||||
|
int ret = mb.exec();
|
||||||
|
if (ret == QMessageBox::Yes) {
|
||||||
|
QString dumpSaveFileName;
|
||||||
|
int placementFailCounter = 0;
|
||||||
|
do {
|
||||||
|
placementFailCounter++;
|
||||||
|
if (placementFailCounter == 4) {
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dumpSaveFileName = QFileDialog::getSaveFileName(nullptr,
|
||||||
|
QObject::tr("Choose a directory to save the crash dump in"),
|
||||||
|
QStandardPaths::writableLocation(QStandardPaths::HomeLocation) +
|
||||||
|
QDir::separator() +
|
||||||
|
"Cutter_crash_dump_"
|
||||||
|
+ QDate().currentDate().toString("dd.MM.yy") + "_"
|
||||||
|
+ QTime().currentTime().toString() + ".dmp",
|
||||||
|
QObject::tr("Dump files (*.dmp)"));
|
||||||
|
|
||||||
|
if (dumpSaveFileName.isEmpty()) {
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
if (QFile::rename(dumpFileFullPath, dumpSaveFileName)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
QMessageBox::critical(nullptr,
|
||||||
|
QObject::tr("Error"),
|
||||||
|
QObject::tr("Error occured during writing to the %1.<br/>"
|
||||||
|
"Please, make sure you have access to that directory "
|
||||||
|
"and try again.").arg(QFileInfo(dumpSaveFileName).dir().path()));
|
||||||
|
} while (true);
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
QMessageBox info;
|
||||||
|
info.setWindowTitle(QObject::tr("Success"));
|
||||||
|
info.setText(QObject::tr("<a href=\"%1\">Crash dump</a> was successfully created.")
|
||||||
|
.arg(QFileInfo(dumpSaveFileName).dir().path()));
|
||||||
|
info.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||||
|
|
||||||
|
info.button(QMessageBox::Yes)->setText(QObject::tr("Open an issue"));
|
||||||
|
info.button(QMessageBox::No)->setText(QObject::tr("Exit Cutter"));
|
||||||
|
info.setDefaultButton(QMessageBox::Yes);
|
||||||
|
|
||||||
|
int ret = info.exec();
|
||||||
|
if (ret == QMessageBox::Yes) {
|
||||||
|
openIssue();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QMessageBox::critical(nullptr,
|
||||||
|
QObject::tr("Error!"),
|
||||||
|
QObject::tr("Error occured during crash dump creation."));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QFile f(dumpFileFullPath);
|
||||||
|
f.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
_exit(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void initCrashHandler()
|
||||||
|
{
|
||||||
|
#ifdef SIGSEGV
|
||||||
|
signal(SIGSEGV, crashHandler);
|
||||||
|
#endif // SIGSEGV
|
||||||
|
#ifdef SIGILL
|
||||||
|
signal(SIGILL, crashHandler);
|
||||||
|
#endif // SIGILL
|
||||||
|
#ifdef SIGFPE
|
||||||
|
signal(SIGFPE, crashHandler);
|
||||||
|
#endif // SIGFPE
|
||||||
|
#ifdef SIGABRT
|
||||||
|
signal(SIGABRT, crashHandler);
|
||||||
|
#endif // SIGABRT
|
||||||
|
#ifdef SIGBUS
|
||||||
|
signal(SIGBUS, crashHandler);
|
||||||
|
#endif // SIGBUS
|
||||||
|
#ifdef SIGPIPE
|
||||||
|
signal(SIGPIPE, crashHandler);
|
||||||
|
#endif // SIGPIPE
|
||||||
|
#ifdef SIGSYS
|
||||||
|
signal(SIGSYS, crashHandler);
|
||||||
|
#endif // SIGSYS
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // CUTTER_ENABLE_CRASH_REPORTS
|
||||||
|
|
||||||
|
void initCrashHandler()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CUTTER_ENABLE_CRASH_REPORTS
|
13
src/common/CrashHandler.h
Normal file
13
src/common/CrashHandler.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef CRASH_HANDLER_H
|
||||||
|
#define CRASH_HANDLER_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fn void initCrashHandler()
|
||||||
|
*
|
||||||
|
* If CUTTER_ENABLE_CRASH_REPORTS is true, initializes
|
||||||
|
* crash handling and reporting, otherwise does nothing.
|
||||||
|
*/
|
||||||
|
void initCrashHandler();
|
||||||
|
|
||||||
|
|
||||||
|
#endif // CRASH_HANDLER_H
|
@ -9,6 +9,7 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
|
#include "core/CutterCommon.h"
|
||||||
|
|
||||||
struct FunctionDescription {
|
struct FunctionDescription {
|
||||||
RVA offset;
|
RVA offset;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "ui_MainWindow.h"
|
#include "ui_MainWindow.h"
|
||||||
|
|
||||||
// Common Headers
|
// Common Headers
|
||||||
|
#include "common/BugReporting.h"
|
||||||
#include "common/Highlighter.h"
|
#include "common/Highlighter.h"
|
||||||
#include "common/HexAsciiHighlighter.h"
|
#include "common/HexAsciiHighlighter.h"
|
||||||
#include "common/Helpers.h"
|
#include "common/Helpers.h"
|
||||||
@ -1112,34 +1113,10 @@ void MainWindow::on_actionAbout_triggered()
|
|||||||
a->setAttribute(Qt::WA_DeleteOnClose);
|
a->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
a->open();
|
a->open();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionIssue_triggered()
|
void MainWindow::on_actionIssue_triggered()
|
||||||
{
|
{
|
||||||
QString url, osInfo, format, arch, type;
|
openIssue();
|
||||||
//Pull in info needed for git issue
|
|
||||||
osInfo = QString(QSysInfo::productType()) + " " + QString(QSysInfo::productVersion());
|
|
||||||
QJsonDocument docu = Core()->getFileInfo();
|
|
||||||
QJsonObject coreObj = docu.object()["core"].toObject();
|
|
||||||
QJsonObject binObj = docu.object()["bin"].toObject();
|
|
||||||
if (!binObj.QJsonObject::isEmpty()) {
|
|
||||||
format = coreObj["format"].toString();
|
|
||||||
arch = binObj["arch"].toString();
|
|
||||||
if (!binObj["type"].isUndefined()) {
|
|
||||||
type = coreObj["type"].toString();
|
|
||||||
} else {
|
|
||||||
type = "N/A";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
format = coreObj["format"].toString();
|
|
||||||
arch = "N/A";
|
|
||||||
type = "N/A";
|
|
||||||
}
|
|
||||||
url =
|
|
||||||
"https://github.com/radareorg/cutter/issues/new?&body=**Environment information**\n* Operating System: "
|
|
||||||
+ osInfo + "\n* Cutter version: " + CUTTER_VERSION_FULL +
|
|
||||||
"\n* File format: " + format + "\n * Arch: " + arch + "\n * Type: " + type +
|
|
||||||
"\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Additional context**\nAdd any other context about the problem here.";
|
|
||||||
|
|
||||||
QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionRefresh_Panels_triggered()
|
void MainWindow::on_actionRefresh_Panels_triggered()
|
||||||
|
Loading…
Reference in New Issue
Block a user