mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-18 10:56:11 +00:00
Merge branch 'dev' into fix-stringcolumn-resizing
This commit is contained in:
commit
312e4d596e
@ -1,4 +1,4 @@
|
||||
version: '2.0-git-{build}'
|
||||
version: '2.2.0-git-{build}'
|
||||
image: 'Visual Studio 2017'
|
||||
clone_depth: 1
|
||||
|
||||
@ -30,7 +30,6 @@ install:
|
||||
|
||||
before_build:
|
||||
- cmd: git submodule update --init --recursive
|
||||
- scripts\prepare_breakpad.bat
|
||||
|
||||
# Build config
|
||||
build_script:
|
||||
@ -48,7 +47,6 @@ build_script:
|
||||
-DCUTTER_PACKAGE_RZ_GHIDRA=ON
|
||||
-DCUTTER_PACKAGE_JSDEC=ON
|
||||
-DCUTTER_ENABLE_DEPENDENCY_DOWNLOADS=ON
|
||||
-DCUTTER_ENABLE_CRASH_REPORTS=ON
|
||||
-DCMAKE_PREFIX_PATH=%CUTTER_DEPS%\\pyside
|
||||
-DCPACK_PACKAGE_FILE_NAME=%PACKAGE_NAME%
|
||||
-G Ninja
|
||||
@ -80,7 +78,8 @@ for:
|
||||
-
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- dev
|
||||
- stable
|
||||
-
|
||||
skip_non_tags: true
|
||||
|
||||
|
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -2,9 +2,9 @@ blank_issues_enabled: false
|
||||
|
||||
contact_links:
|
||||
- name: Questions Telegram
|
||||
url: https://t.me/r2cutter
|
||||
url: https://t.me/cutter_re
|
||||
about: Please ask questions about Cutter here or one of the other community channels, not in the issue tracker.
|
||||
|
||||
- name: Questions IRC
|
||||
url: https://web.libera.chat/#cutter
|
||||
about: "#cutter on https://web.libera.chat/"
|
||||
about: "#cutter on https://web.libera.chat/"
|
||||
|
273
.github/workflows/ccpp.yml
vendored
273
.github/workflows/ccpp.yml
vendored
@ -1,273 +0,0 @@
|
||||
name: Cutter CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- v*
|
||||
- upload-test*
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-18.04, ubuntu-16.04, macos-latest, windows-2016]
|
||||
python-version: [3.7.x]
|
||||
system-deps: [false]
|
||||
cc-override: [default]
|
||||
cxx-override: [default]
|
||||
include:
|
||||
- os: windows-2016
|
||||
package: true
|
||||
- os: ubuntu-16.04 # ensure that Cutter can be built at least in basic config on Ubuntu 16.04 using sytem libraries
|
||||
python-version: 3.5.10
|
||||
system-deps: true
|
||||
cc-override: '/usr/bin/gcc-5'
|
||||
cxx-override: '/usr/bin/g++-5'
|
||||
- os: ubuntu-16.04 # release package build
|
||||
system-deps: false
|
||||
package: true
|
||||
# Prevent one job from pausing the rest
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
persist-credentials: false
|
||||
- name: apt dependencies
|
||||
if: contains(matrix.os, 'ubuntu')
|
||||
run: |
|
||||
sudo apt-get install libgraphviz-dev mesa-common-dev libxkbcommon-x11-dev libclang-8-dev llvm-8
|
||||
if [[ "${{ matrix.os }}" = "ubuntu-16.04" ]]
|
||||
then
|
||||
sudo apt-get install ninja-build/xenial-backports libxcb1-dev libxkbcommon-dev libxcb-*-dev
|
||||
if [[ "${{ matrix.system-deps }}" = "true" ]]
|
||||
then
|
||||
sudo apt-get install cmake
|
||||
sudo apt-get install --allow-downgrades \
|
||||
g++-5=5.4.\* \
|
||||
gcc-5=5.4.\* \
|
||||
gcc-5-base=5.4.\* \
|
||||
libstdc++-5-dev=5.4.\* \
|
||||
cpp-5=5.4.\* \
|
||||
libgcc-5-dev=5.4.\* \
|
||||
libasan2=5.4.\* \
|
||||
libmpx0=5.4.\*
|
||||
fi
|
||||
# make sure cmake that was just installed is at the front of path before
|
||||
# additional software installed by GitHub
|
||||
echo /usr/bin >> $GITHUB_PATH
|
||||
else
|
||||
sudo apt-get install ninja-build
|
||||
fi
|
||||
if [[ "${{ matrix.system-deps }}" = "true" ]]
|
||||
then
|
||||
sudo apt-get install qt5-default libqt5svg5-dev qttools5-dev qttools5-dev-tools
|
||||
fi
|
||||
- uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: homebrew dependencies
|
||||
if: contains(matrix.os, 'macos')
|
||||
run: |
|
||||
cd scripts
|
||||
rm '/usr/local/bin/2to3' # symlink to some kind of existing python2.7 installation conflicts with brew python3 which gets installed as indirect dependency
|
||||
brew update --preinstall # temporary workaround for https://github.com/Homebrew/homebrew-bundle/issues/751
|
||||
brew bundle
|
||||
brew install coreutils
|
||||
brew install pkg-config
|
||||
- name: py dependencies
|
||||
run: |
|
||||
# 0.56.1 doesn't work with python 3.5 on Ubuntu 16.04
|
||||
pip install meson==0.56.0
|
||||
- name: Prepare package id
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "${{ startsWith(github.event.ref, 'refs/tags')}}" = "true" ]]
|
||||
then
|
||||
PACKAGE_ID="${{ github.event.ref }}"
|
||||
else
|
||||
PACKAGE_ID="git-`date "+%Y-%m-%d"`-${{ format('{0}', github.sha) }}"
|
||||
fi
|
||||
PACKAGE_ID=${PACKAGE_ID##refs/tags/}
|
||||
echo PACKAGE_ID=$PACKAGE_ID >> $GITHUB_ENV
|
||||
- name: cmake ubuntu
|
||||
if: contains(matrix.os, 'ubuntu')
|
||||
run: |
|
||||
if [[ "${{ matrix.system-deps }}" = "false" ]]
|
||||
then
|
||||
scripts/fetch_deps.sh
|
||||
source cutter-deps/env.sh
|
||||
export PKG_CONFIG_PATH="$CUTTER_DEPS_PYTHON_PREFIX/lib/pkgconfig:${PKG_CONFIG_PATH:-}"
|
||||
export LD_LIBRARY_PATH="`llvm-config --libdir`:$LD_LIBRARY_PATH"
|
||||
fi
|
||||
set -euo pipefail #TODO: move to top once cutter-deps doesn't fail
|
||||
if [[ "${{ matrix.cc-override }}" != "default" ]]
|
||||
then
|
||||
export CC="${{matrix.cc-override}}"
|
||||
export CXX="${{matrix.cxx-override}}"
|
||||
fi
|
||||
|
||||
source scripts/prepare_breakpad_linux.sh
|
||||
export PKG_CONFIG_PATH="$CUSTOM_BREAKPAD_PREFIX/lib/pkgconfig:${PKG_CONFIG_PATH:-}" #
|
||||
mkdir build
|
||||
cd build
|
||||
cmake --version
|
||||
if [[ "${{ matrix.system-deps }}" = "false" ]]
|
||||
then
|
||||
cmake \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCUTTER_ENABLE_PYTHON=ON \
|
||||
-DPYTHON_LIBRARY="$CUTTER_DEPS_PYTHON_PREFIX/lib/libpython3.9.so" \
|
||||
-DPYTHON_INCLUDE_DIR="$CUTTER_DEPS_PYTHON_PREFIX/include/python3.9" \
|
||||
-DPYTHON_EXECUTABLE="$CUTTER_DEPS_PYTHON_PREFIX/bin/python3" \
|
||||
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON \
|
||||
-DCUTTER_ENABLE_GRAPHVIZ=OFF \
|
||||
-DCUTTER_ENABLE_CRASH_REPORTS=ON \
|
||||
-DCUTTER_USE_BUNDLED_RIZIN=ON \
|
||||
-DCUTTER_APPIMAGE_BUILD=ON \
|
||||
-DCUTTER_ENABLE_PACKAGING=ON \
|
||||
-DCUTTER_ENABLE_DEPENDENCY_DOWNLOADS=ON \
|
||||
-DCUTTER_PACKAGE_RZ_GHIDRA=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=appdir/usr \
|
||||
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON \
|
||||
..
|
||||
else
|
||||
cmake \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCUTTER_USE_BUNDLED_RIZIN=ON \
|
||||
..
|
||||
fi
|
||||
ninja
|
||||
if [[ "${{ matrix.package || false }}" = "true" ]]
|
||||
then
|
||||
export CUTTER_VERSION=$(python ../scripts/get_version.py)
|
||||
export VERSION=$CUTTER_VERSION
|
||||
ninja install
|
||||
"../scripts/appimage_embed_python.sh" appdir
|
||||
APP_PREFIX=`pwd`/appdir/usr
|
||||
# export LD_LIBRARY_PATH=${APP_PREFIX}/lib:$Shiboken2_ROOT/lib
|
||||
export PATH=$PATH:${APP_PREFIX}/bin
|
||||
"../scripts/jsdec.sh" --prefix=`pwd`/appdir/usr
|
||||
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/6/linuxdeployqt-6-x86_64.AppImage"
|
||||
chmod a+x linuxdeployqt*.AppImage
|
||||
rm -fv "../cutter-deps/qt/plugins/imageformats/libqjp2.so"
|
||||
# ./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -executable=./appdir/usr/bin/python3 -bundle-non-qt-libs -no-strip -exclude-libs=libnss3.so,libnssutil3.so,libqjp2.so -ignore-glob=usr/lib/python3.9/**/* -verbose=2
|
||||
# exclude librzghidra cutter plugin because cutter and rz plugin is loaded manuallly as they are plugins linuxdeployqt doesn't know this
|
||||
./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop \
|
||||
-executable=./appdir/usr/bin/python3 \
|
||||
-appimage \
|
||||
-no-strip -exclude-libs=libnss3.so,libnssutil3.so,libqjp2.so \
|
||||
-ignore-glob=usr/lib/python3.9/**/* \
|
||||
-ignore-glob=usr/share/rizin/cutter/plugins/native/librz_ghidra_cutter.so \
|
||||
-verbose=2
|
||||
find ./appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq
|
||||
export APPIMAGE_FILE="Cutter-${PACKAGE_ID}-x64.Linux.AppImage"
|
||||
mv Cutter-*-x86_64.AppImage "$APPIMAGE_FILE"
|
||||
echo PACKAGE_NAME=$APPIMAGE_FILE >> $GITHUB_ENV
|
||||
echo UPLOAD_ASSET_TYPE=application/x-executable >> $GITHUB_ENV
|
||||
fi
|
||||
- name: cmake macos
|
||||
shell: bash
|
||||
if: contains(matrix.os, 'macos')
|
||||
run: |
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.14
|
||||
scripts/fetch_deps.sh
|
||||
source cutter-deps/env.sh
|
||||
set -euo pipefail
|
||||
export PATH=/usr/local/opt/llvm/bin:$PATH
|
||||
source scripts/prepare_breakpad_macos.sh
|
||||
mkdir build
|
||||
cd build
|
||||
PACKAGE_NAME=Cutter-${PACKAGE_ID}-x64.macOS
|
||||
cmake \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DPYTHON_LIBRARY="$CUTTER_DEPS_PYTHON_PREFIX/lib/libpython3.9.dylib" \
|
||||
-DPYTHON_INCLUDE_DIR="$CUTTER_DEPS_PYTHON_PREFIX/include/python3.9" \
|
||||
-DPYTHON_EXECUTABLE="$CUTTER_DEPS_PYTHON_PREFIX/bin/python3" \
|
||||
-DCUTTER_ENABLE_PYTHON=ON \
|
||||
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON \
|
||||
-DCUTTER_ENABLE_CRASH_REPORTS=ON \
|
||||
-DCUTTER_USE_BUNDLED_RIZIN=ON \
|
||||
-DCUTTER_ENABLE_PACKAGING=ON \
|
||||
-DCUTTER_PACKAGE_DEPENDENCIES=ON \
|
||||
-DCUTTER_ENABLE_DEPENDENCY_DOWNLOADS=ON \
|
||||
-DCUTTER_PACKAGE_RZ_GHIDRA=ON \
|
||||
-DCUTTER_PACKAGE_JSDEC=ON \
|
||||
-DCPACK_PACKAGE_FILE_NAME="$PACKAGE_NAME" \
|
||||
-DCMAKE_FRAMEWORK_PATH="$BREAKPAD_FRAMEWORK_DIR" \
|
||||
-DCPACK_BUNDLE_APPLE_CERT_APP="-" \
|
||||
.. && \
|
||||
make -j4;
|
||||
make package
|
||||
export CUTTER_VERSION=$(python3 ../scripts/get_version.py)
|
||||
echo PACKAGE_NAME=${PACKAGE_NAME}.dmg >> $GITHUB_ENV
|
||||
echo UPLOAD_ASSET_TYPE=application/x-apple-diskimage >> $GITHUB_ENV
|
||||
- name: windows dependencies
|
||||
if: contains(matrix.os, 'windows')
|
||||
shell: bash
|
||||
run: |
|
||||
pip install ninja
|
||||
scripts/fetch_deps.sh
|
||||
choco install winflexbison3
|
||||
- name: windows cmake
|
||||
if: contains(matrix.os, 'windows')
|
||||
shell: cmd
|
||||
run: |
|
||||
set ARCH=x64
|
||||
set CUTTER_DEPS=%CD%\cutter-deps
|
||||
set PATH=%CD%\cutter-deps\qt\bin;%PATH%
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
call scripts\prepare_breakpad.bat
|
||||
cd
|
||||
mkdir build
|
||||
cd build
|
||||
set PACKAGE_NAME=cutter-%PACKAGE_ID%-x64.Windows
|
||||
cmake ^
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
-DCUTTER_USE_BUNDLED_RIZIN=ON ^
|
||||
-DCUTTER_ENABLE_PYTHON=ON ^
|
||||
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON ^
|
||||
-DCUTTER_ENABLE_PACKAGING=ON ^
|
||||
-DCUTTER_PACKAGE_DEPENDENCIES=ON ^
|
||||
-DCUTTER_PACKAGE_RZ_GHIDRA=ON ^
|
||||
-DCUTTER_PACKAGE_JSDEC=ON ^
|
||||
-DCUTTER_ENABLE_DEPENDENCY_DOWNLOADS=ON ^
|
||||
-DCUTTER_ENABLE_CRASH_REPORTS=ON ^
|
||||
-DCMAKE_PREFIX_PATH="%CUTTER_DEPS%\pyside" ^
|
||||
-DCPACK_PACKAGE_FILE_NAME=%PACKAGE_NAME% ^
|
||||
-G Ninja ^
|
||||
..
|
||||
cmake --build . --config Release
|
||||
cmake --build . --config Release --target package
|
||||
echo PACKAGE_NAME=%PACKAGE_NAME%.zip >> %GITHUB_ENV%
|
||||
echo UPLOAD_ASSET_TYPE=application/zip >> %GITHUB_ENV%
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: env.PACKAGE_NAME != null
|
||||
with:
|
||||
name: ${{ env.PACKAGE_NAME }}
|
||||
path: build/${{ env.PACKAGE_NAME }}
|
||||
- name: Get release
|
||||
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
|
||||
id: get_release
|
||||
uses: karliss/get-release@23b8b7144dd5b0c9d6942b2fb78bd9ae71546d03
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Upload release assets
|
||||
if: steps.get_release.outputs.upload_url != null && env.PACKAGE_NAME != null
|
||||
uses: actions/upload-release-asset@v1.0.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.get_release.outputs.upload_url }}
|
||||
asset_path: build/${{ env.PACKAGE_NAME }}
|
||||
asset_name: ${{ env.PACKAGE_NAME }}
|
||||
asset_content_type: ${{ env.UPLOAD_ASSET_TYPE }}
|
450
.github/workflows/ci.yml
vendored
Normal file
450
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,450 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- stable
|
||||
tags:
|
||||
- v*
|
||||
- upload-test*
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- dev
|
||||
- stable
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-linux:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ${{ matrix.image }}
|
||||
options: --privileged
|
||||
strategy:
|
||||
matrix:
|
||||
name: [
|
||||
linux-x86_64,
|
||||
linux-x86_64-system-deps,
|
||||
linux-x86_64-qt6-system-deps,
|
||||
tarball
|
||||
]
|
||||
include:
|
||||
- name: linux-x86_64-system-deps # ensure that Cutter can be built at least in basic config on Ubuntu 18.04 using sytem libraries
|
||||
image: ubuntu:18.04
|
||||
python-version: 3.6.x
|
||||
system-deps: true
|
||||
package: false
|
||||
tarball: false
|
||||
cc-override: '/usr/bin/gcc-7'
|
||||
cxx-override: '/usr/bin/g++-7'
|
||||
- name: linux-x86_64-qt6-system-deps # ensure that Cutter can be built at least in basic config on Ubuntu 22.04 using sytem libraries
|
||||
image: ubuntu:22.04
|
||||
python-version: 3.10.x
|
||||
system-deps: true
|
||||
package: false
|
||||
tarball: false
|
||||
cc-override: '/usr/bin/gcc-12'
|
||||
cxx-override: '/usr/bin/g++-12'
|
||||
- name: linux-x86_64
|
||||
image: ubuntu:18.04
|
||||
python-version: 3.6.x
|
||||
system-deps: false
|
||||
package: true
|
||||
tarball: false
|
||||
cc-override: default
|
||||
cxx-override: default
|
||||
- name: tarball
|
||||
python-version: 3.6.x
|
||||
image: ubuntu:20.04
|
||||
system-deps: false
|
||||
package: false
|
||||
tarball: true
|
||||
# Prevent one job from pausing the rest
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: set timezone
|
||||
run: |
|
||||
# Fix timezone on ubuntu to prevent user input request during the apt-get phase.
|
||||
export TZ=UTC
|
||||
ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||
|
||||
- name: install latest git and cmake
|
||||
shell: bash
|
||||
run: |
|
||||
set -e
|
||||
apt-get -y update
|
||||
echo "Using image: ${{ matrix.image }}"
|
||||
|
||||
export GIT_VERSION="git-2.36.1"
|
||||
export CMAKE_VERSION="3.25.3"
|
||||
|
||||
apt-get -y install wget libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev build-essential
|
||||
|
||||
wget "https://www.kernel.org/pub/software/scm/git/$GIT_VERSION.tar.gz"
|
||||
tar -zxf "$GIT_VERSION.tar.gz"
|
||||
|
||||
# build.
|
||||
make -C "$GIT_VERSION" prefix=/usr install -j > "$GIT_VERSION/build.log"
|
||||
|
||||
# ensure git is installed.
|
||||
git version
|
||||
|
||||
wget "https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-linux-x86_64.sh"
|
||||
bash ./cmake-$CMAKE_VERSION-linux-x86_64.sh --skip-license --prefix=/usr
|
||||
|
||||
# ensure cmake is installed.
|
||||
cmake --version
|
||||
|
||||
# cleanup dev environment.
|
||||
rm -rf "$GIT_VERSION.tar.gz" "$GIT_VERSION" cmake-$CMAKE_VERSION-linux-x86_64.sh
|
||||
unset CMAKE_VERSION
|
||||
unset GIT_VERSION
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
persist-credentials: false
|
||||
|
||||
- name: apt cutter dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
# install needed packages
|
||||
apt-get -y install libgraphviz-dev \
|
||||
mesa-common-dev \
|
||||
libxkbcommon-x11-dev \
|
||||
ninja-build \
|
||||
python3-pip \
|
||||
curl \
|
||||
libpcre2-dev \
|
||||
libfuse2 \
|
||||
pkg-config
|
||||
|
||||
if [ "${{ matrix.image }}" = "ubuntu:18.04" ]; then
|
||||
# install additional packages needed for appimage
|
||||
apt-get -y install gcc-7 \
|
||||
libglu1-mesa-dev \
|
||||
freeglut3-dev \
|
||||
mesa-common-dev
|
||||
|
||||
fi
|
||||
if [ "${{ matrix.image }}" = "ubuntu:18.04" ] || [ "${{ matrix.image }}" = "ubuntu:20.04" ]; then
|
||||
# install additional packages needed for appimage
|
||||
apt-get -y install libxcb1-dev \
|
||||
libxkbcommon-dev \
|
||||
libxcb-*-dev \
|
||||
libegl1 \
|
||||
libclang-8-dev \
|
||||
llvm-8
|
||||
ln -s /usr/bin/llvm-config-8 /usr/bin/llvm-config
|
||||
fi
|
||||
if [ "${{ matrix.image }}" = "ubuntu:18.04" ] && [ "${{ matrix.system-deps }}" = "true" ]; then
|
||||
apt-get -y install qt5-default \
|
||||
libqt5svg5-dev \
|
||||
qttools5-dev \
|
||||
qttools5-dev-tools
|
||||
fi
|
||||
if [ "${{ matrix.image }}" = "ubuntu:22.04" ]; then
|
||||
apt-get -y install libclang-12-dev \
|
||||
llvm-12 \
|
||||
qt6-base-dev \
|
||||
qt6-tools-dev \
|
||||
qt6-tools-dev-tools \
|
||||
libqt6svg6-dev \
|
||||
libqt6core5compat6-dev \
|
||||
libqt6svgwidgets6 \
|
||||
qt6-l10n-tools \
|
||||
gcc-12 \
|
||||
g++-12
|
||||
fi
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: py dependencies
|
||||
run: |
|
||||
# https://github.com/rizinorg/cutter/runs/7170222817?check_suite_focus=true
|
||||
python3 -m pip install meson==0.61.5
|
||||
- name: Prepare package id
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ startsWith(github.event.ref, 'refs/tags')}}" = "true" ]
|
||||
then
|
||||
PACKAGE_ID="${{ github.event.ref }}"
|
||||
else
|
||||
PACKAGE_ID="git-`date "+%Y-%m-%d"`-${{ format('{0}', github.sha) }}"
|
||||
fi
|
||||
PACKAGE_ID=${PACKAGE_ID##refs/tags/}
|
||||
echo PACKAGE_ID=$PACKAGE_ID >> $GITHUB_ENV
|
||||
- name: cmake ubuntu
|
||||
shell: bash
|
||||
run: |
|
||||
if [ "${{ matrix.system-deps }}" = "false" ]
|
||||
then
|
||||
scripts/fetch_deps.sh
|
||||
. cutter-deps/env.sh
|
||||
export PKG_CONFIG_PATH="$CUTTER_DEPS_PYTHON_PREFIX/lib/pkgconfig:${PKG_CONFIG_PATH:-}"
|
||||
export LD_LIBRARY_PATH="`llvm-config --libdir`:$LD_LIBRARY_PATH"
|
||||
fi
|
||||
set -e #TODO: move to top once cutter-deps doesn't fail
|
||||
if [ "${{ matrix.cc-override }}" != "default" ]
|
||||
then
|
||||
export CC="${{matrix.cc-override}}"
|
||||
export CXX="${{matrix.cxx-override}}"
|
||||
fi
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
if [ "${{ matrix.system-deps }}" = "false" ]
|
||||
then
|
||||
cmake \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCUTTER_ENABLE_PYTHON=ON \
|
||||
-DPYTHON_LIBRARY="$CUTTER_DEPS_PYTHON_PREFIX/lib/libpython3.9.so" \
|
||||
-DPYTHON_INCLUDE_DIR="$CUTTER_DEPS_PYTHON_PREFIX/include/python3.9" \
|
||||
-DPYTHON_EXECUTABLE="$CUTTER_DEPS_PYTHON_PREFIX/bin/python3" \
|
||||
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON \
|
||||
-DCUTTER_ENABLE_GRAPHVIZ=ON \
|
||||
-DCUTTER_USE_BUNDLED_RIZIN=ON \
|
||||
-DCUTTER_APPIMAGE_BUILD=ON \
|
||||
-DCUTTER_ENABLE_PACKAGING=ON \
|
||||
-DCUTTER_ENABLE_KSYNTAXHIGHLIGHTING=OFF \
|
||||
-DCUTTER_ENABLE_SIGDB=ON \
|
||||
-DCUTTER_ENABLE_DEPENDENCY_DOWNLOADS=ON \
|
||||
-DCUTTER_PACKAGE_RZ_GHIDRA=ON \
|
||||
-DCUTTER_PACKAGE_JSDEC=ON \
|
||||
-DCUTTER_PACKAGE_RZ_LIBSWIFT=ON \
|
||||
-DCUTTER_PACKAGE_RZ_LIBYARA=ON \
|
||||
-DCUTTER_PACKAGE_RZ_SILHOUETTE=ON \
|
||||
-DCMAKE_INSTALL_PREFIX=appdir/usr \
|
||||
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON \
|
||||
..
|
||||
elif [ "${{ matrix.image }}" = "ubuntu:22.04" ]
|
||||
then
|
||||
cmake \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCUTTER_QT6=ON \
|
||||
-DCUTTER_USE_BUNDLED_RIZIN=ON \
|
||||
..
|
||||
else
|
||||
cmake \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCUTTER_USE_BUNDLED_RIZIN=ON \
|
||||
..
|
||||
fi
|
||||
ninja
|
||||
if [ "${{ matrix.package }}" = "true" ]
|
||||
then
|
||||
export CUTTER_VERSION=$(python ../scripts/get_version.py)
|
||||
export VERSION=$CUTTER_VERSION
|
||||
ninja install
|
||||
"../scripts/appimage_embed_python.sh" appdir
|
||||
APP_PREFIX=`pwd`/appdir/usr
|
||||
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$APP_PREFIX/lib/rizin/plugins"
|
||||
export PATH=$PATH:${APP_PREFIX}/bin
|
||||
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage"
|
||||
chmod a+x linuxdeployqt*.AppImage
|
||||
rm -fv "../cutter-deps/qt/plugins/imageformats/libqjp2.so"
|
||||
./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop \
|
||||
-executable=./appdir/usr/bin/python3 \
|
||||
-appimage \
|
||||
-no-strip -exclude-libs=libnss3.so,libnssutil3.so,libqjp2.so \
|
||||
-ignore-glob=usr/lib/python3.9/**/* \
|
||||
-verbose=2
|
||||
find ./appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq
|
||||
export APPIMAGE_FILE="Cutter-${PACKAGE_ID}-Linux-x86_64.AppImage"
|
||||
mv Cutter-*-x86_64.AppImage "$APPIMAGE_FILE"
|
||||
echo PACKAGE_NAME=$APPIMAGE_FILE >> $GITHUB_ENV
|
||||
echo PACKAGE_PATH=build/$APPIMAGE_FILE >> $GITHUB_ENV
|
||||
echo UPLOAD_ASSET_TYPE=application/x-executable >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Create tarball
|
||||
if: matrix.tarball
|
||||
shell: bash
|
||||
run: |
|
||||
scripts/tarball.sh "Cutter-${PACKAGE_ID}"
|
||||
echo PACKAGE_NAME=Cutter-${PACKAGE_ID}-src.tar.gz >> $GITHUB_ENV
|
||||
echo PACKAGE_PATH=Cutter-${PACKAGE_ID}-src.tar.gz >> $GITHUB_ENV
|
||||
echo UPLOAD_ASSET_TYPE=application/gzip >> $GITHUB_ENV
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: env.PACKAGE_NAME != null
|
||||
with:
|
||||
name: ${{ env.PACKAGE_NAME }}
|
||||
path: ${{ env.PACKAGE_PATH }}
|
||||
- name: Get release
|
||||
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
|
||||
id: get_release
|
||||
uses: rizinorg/gha-get-release@c8074dd5d13ddd0a194d8c9205a1466973c7dc0d
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Upload release assets
|
||||
if: steps.get_release.outputs.upload_url != null && env.PACKAGE_NAME != null
|
||||
uses: actions/upload-release-asset@v1.0.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.get_release.outputs.upload_url }}
|
||||
asset_path: ${{ env.PACKAGE_PATH }}
|
||||
asset_name: ${{ env.PACKAGE_NAME }}
|
||||
asset_content_type: ${{ env.UPLOAD_ASSET_TYPE }}
|
||||
|
||||
build:
|
||||
name: ${{ matrix.name }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
name: [
|
||||
macos-x86_64,
|
||||
windows-x86_64,
|
||||
]
|
||||
include:
|
||||
- name: windows-x86_64
|
||||
os: windows-2019
|
||||
package: true
|
||||
system-deps: false
|
||||
python-version: 3.7.x
|
||||
- name: macos-x86_64
|
||||
os: macos-latest
|
||||
python-version: 3.7.x
|
||||
system-deps: false
|
||||
package: true
|
||||
cc-override: default
|
||||
cxx-override: default
|
||||
# Prevent one job from pausing the rest
|
||||
fail-fast: false
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
persist-credentials: false
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: homebrew dependencies
|
||||
if: contains(matrix.os, 'macos')
|
||||
run: |
|
||||
cd scripts
|
||||
rm /usr/local/bin/2to3* # symlink to some kind of existing python2.7 installation conflicts with brew python3 which gets installed as indirect dependency
|
||||
brew bundle
|
||||
- name: py dependencies
|
||||
run: |
|
||||
python3 -m pip install -U pip==21.3.1
|
||||
pip install meson==0.61.5 # https://github.com/rizinorg/cutter/runs/7170222817?check_suite_focus=true
|
||||
- name: Prepare package id
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "${{ startsWith(github.event.ref, 'refs/tags')}}" = "true" ]]
|
||||
then
|
||||
PACKAGE_ID="${{ github.event.ref }}"
|
||||
else
|
||||
PACKAGE_ID="git-`date "+%Y-%m-%d"`-${{ format('{0}', github.sha) }}"
|
||||
fi
|
||||
PACKAGE_ID=${PACKAGE_ID##refs/tags/}
|
||||
echo PACKAGE_ID=$PACKAGE_ID >> $GITHUB_ENV
|
||||
- name: cmake macos
|
||||
shell: bash
|
||||
if: contains(matrix.os, 'macos')
|
||||
run: |
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.14
|
||||
scripts/fetch_deps.sh
|
||||
source cutter-deps/env.sh
|
||||
set -euo pipefail
|
||||
export PATH=/usr/local/opt/llvm/bin:$PATH
|
||||
mkdir build
|
||||
cd build
|
||||
PACKAGE_NAME=Cutter-${PACKAGE_ID}-macOS-x86_64
|
||||
cmake \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DPYTHON_LIBRARY="$CUTTER_DEPS_PYTHON_PREFIX/lib/libpython3.9.dylib" \
|
||||
-DPYTHON_INCLUDE_DIR="$CUTTER_DEPS_PYTHON_PREFIX/include/python3.9" \
|
||||
-DPYTHON_EXECUTABLE="$CUTTER_DEPS_PYTHON_PREFIX/bin/python3" \
|
||||
-DCUTTER_ENABLE_PYTHON=ON \
|
||||
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON \
|
||||
-DCUTTER_USE_BUNDLED_RIZIN=ON \
|
||||
-DCUTTER_ENABLE_PACKAGING=ON \
|
||||
-DCUTTER_ENABLE_SIGDB=ON \
|
||||
-DCUTTER_PACKAGE_DEPENDENCIES=ON \
|
||||
-DCUTTER_ENABLE_DEPENDENCY_DOWNLOADS=ON \
|
||||
-DCUTTER_PACKAGE_RZ_GHIDRA=ON \
|
||||
-DCUTTER_PACKAGE_JSDEC=ON \
|
||||
-DCUTTER_PACKAGE_RZ_LIBSWIFT=ON \
|
||||
-DCUTTER_PACKAGE_RZ_LIBYARA=ON \
|
||||
-DCUTTER_PACKAGE_RZ_SILHOUETTE=ON \
|
||||
-DCPACK_PACKAGE_FILE_NAME="$PACKAGE_NAME" \
|
||||
-DCPACK_BUNDLE_APPLE_CERT_APP="-" \
|
||||
.. && \
|
||||
make -j4;
|
||||
make package
|
||||
export CUTTER_VERSION=$(python3 ../scripts/get_version.py)
|
||||
echo PACKAGE_NAME=${PACKAGE_NAME}.dmg >> $GITHUB_ENV
|
||||
echo PACKAGE_PATH=build/${PACKAGE_NAME}.dmg >> $GITHUB_ENV
|
||||
echo UPLOAD_ASSET_TYPE=application/x-apple-diskimage >> $GITHUB_ENV
|
||||
- name: windows dependencies
|
||||
if: contains(matrix.os, 'windows')
|
||||
shell: bash
|
||||
run: |
|
||||
pip install ninja
|
||||
scripts/fetch_deps.sh
|
||||
choco install winflexbison3
|
||||
- name: windows cmake
|
||||
if: contains(matrix.os, 'windows')
|
||||
shell: cmd
|
||||
run: |
|
||||
set ARCH=x64
|
||||
set CUTTER_DEPS=%CD%\cutter-deps
|
||||
set PATH=%CD%\cutter-deps\qt\bin;%PATH%
|
||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64
|
||||
cd
|
||||
mkdir build
|
||||
cd build
|
||||
set PACKAGE_NAME=Cutter-%PACKAGE_ID%-Windows-x86_64
|
||||
cmake ^
|
||||
-DCMAKE_BUILD_TYPE=Release ^
|
||||
-DCUTTER_USE_BUNDLED_RIZIN=ON ^
|
||||
-DCUTTER_ENABLE_PYTHON=ON ^
|
||||
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON ^
|
||||
-DCUTTER_ENABLE_PACKAGING=ON ^
|
||||
-DCUTTER_ENABLE_SIGDB=ON ^
|
||||
-DCUTTER_PACKAGE_DEPENDENCIES=ON ^
|
||||
-DCUTTER_PACKAGE_RZ_GHIDRA=ON ^
|
||||
-DCUTTER_PACKAGE_RZ_LIBSWIFT=ON ^
|
||||
-DCUTTER_PACKAGE_RZ_LIBYARA=ON ^
|
||||
-DCUTTER_PACKAGE_RZ_SILHOUETTE=ON ^
|
||||
-DCUTTER_PACKAGE_JSDEC=ON ^
|
||||
-DCUTTER_ENABLE_DEPENDENCY_DOWNLOADS=ON ^
|
||||
-DCMAKE_PREFIX_PATH="%CUTTER_DEPS%\pyside" ^
|
||||
-DCPACK_PACKAGE_FILE_NAME=%PACKAGE_NAME% ^
|
||||
-G Ninja ^
|
||||
..
|
||||
cmake --build . --config Release
|
||||
cmake --build . --config Release --target package
|
||||
echo PACKAGE_NAME=%PACKAGE_NAME%.zip >> %GITHUB_ENV%
|
||||
echo PACKAGE_PATH=build/%PACKAGE_NAME%.zip >> %GITHUB_ENV%
|
||||
echo UPLOAD_ASSET_TYPE=application/zip >> %GITHUB_ENV%
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: env.PACKAGE_NAME != null
|
||||
with:
|
||||
name: ${{ env.PACKAGE_NAME }}
|
||||
path: ${{ env.PACKAGE_PATH }}
|
||||
- name: Get release
|
||||
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
|
||||
id: get_release
|
||||
uses: rizinorg/gha-get-release@c8074dd5d13ddd0a194d8c9205a1466973c7dc0d
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Upload release assets
|
||||
if: steps.get_release.outputs.upload_url != null && env.PACKAGE_NAME != null
|
||||
uses: actions/upload-release-asset@v1.0.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.get_release.outputs.upload_url }}
|
||||
asset_path: ${{ env.PACKAGE_PATH }}
|
||||
asset_name: ${{ env.PACKAGE_NAME }}
|
||||
asset_content_type: ${{ env.UPLOAD_ASSET_TYPE }}
|
8
.github/workflows/coverity-scan.yml
vendored
8
.github/workflows/coverity-scan.yml
vendored
@ -7,16 +7,16 @@ jobs:
|
||||
latest:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: actions/setup-python@v1
|
||||
- uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.7.x
|
||||
python-version: 3.9.x
|
||||
|
||||
- name: Download Coverity Build Tool
|
||||
run: |
|
||||
wget -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=$TOKEN&project=radareorg%2Fcutter" -O cov-analysis-linux64.tar.gz
|
||||
wget -q https://scan.coverity.com/download/cxx/linux64 --post-data "token=$TOKEN&project=rizinorg%2Fcutter" -O cov-analysis-linux64.tar.gz
|
||||
mkdir cov-analysis-linux64
|
||||
tar xzf cov-analysis-linux64.tar.gz --strip 1 -C cov-analysis-linux64
|
||||
env:
|
||||
|
6
.github/workflows/docs.yml
vendored
6
.github/workflows/docs.yml
vendored
@ -3,13 +3,13 @@ name: Docs
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: install dependencies
|
||||
|
10
.github/workflows/linter.yml
vendored
10
.github/workflows/linter.yml
vendored
@ -3,10 +3,12 @@ name: "Linter"
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- dev
|
||||
- stable
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- dev
|
||||
- stable
|
||||
|
||||
jobs:
|
||||
changes:
|
||||
@ -14,7 +16,7 @@ jobs:
|
||||
outputs:
|
||||
clang-format: ${{ steps.filter.outputs.clang-format }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dorny/paths-filter@v2
|
||||
id: filter
|
||||
with:
|
||||
@ -31,7 +33,7 @@ jobs:
|
||||
if: ${{ needs.changes.outputs.clang-format == 'true' }}
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install wget
|
||||
run: sudo apt --assume-yes install wget
|
||||
|
47
.woodpecker/macos-arm64.yml
Normal file
47
.woodpecker/macos-arm64.yml
Normal file
@ -0,0 +1,47 @@
|
||||
platform: darwin/arm64
|
||||
|
||||
pipeline:
|
||||
fetch-deps:
|
||||
image: /bin/bash
|
||||
commands:
|
||||
- scripts/fetch_deps.sh
|
||||
build:
|
||||
image: /bin/bash
|
||||
commands:
|
||||
- set -e
|
||||
- export PACKAGE_ID=${CI_COMMIT_TAG=git-`date "+%Y-%m-%d"`-${CI_COMMIT_SHA}}
|
||||
- export PACKAGE_NAME=Cutter-$${PACKAGE_ID}-macOS-arm64
|
||||
- source cutter-deps/env.sh
|
||||
- cmake -Bbuild -GNinja
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DPYTHON_LIBRARY="$$CUTTER_DEPS_PYTHON_PREFIX/lib/libpython3.9.dylib"
|
||||
-DPYTHON_INCLUDE_DIR="$$CUTTER_DEPS_PYTHON_PREFIX/include/python3.9"
|
||||
-DPYTHON_EXECUTABLE="$$CUTTER_DEPS_PYTHON_PREFIX/bin/python3"
|
||||
-DCUTTER_ENABLE_PYTHON=ON
|
||||
-DCUTTER_ENABLE_PYTHON_BINDINGS=ON
|
||||
-DCUTTER_USE_BUNDLED_RIZIN=ON
|
||||
-DCUTTER_ENABLE_PACKAGING=ON
|
||||
-DCUTTER_ENABLE_SIGDB=ON
|
||||
-DCUTTER_PACKAGE_DEPENDENCIES=ON
|
||||
-DCUTTER_ENABLE_DEPENDENCY_DOWNLOADS=ON
|
||||
-DCUTTER_PACKAGE_RZ_GHIDRA=ON
|
||||
-DCUTTER_PACKAGE_JSDEC=ON
|
||||
-DCUTTER_PACKAGE_RZ_LIBSWIFT=ON
|
||||
-DCUTTER_PACKAGE_RZ_LIBYARA=ON
|
||||
-DCUTTER_PACKAGE_RZ_SILHOUETTE=ON
|
||||
-DCPACK_PACKAGE_FILE_NAME="$$PACKAGE_NAME"
|
||||
-DCPACK_BUNDLE_APPLE_CERT_APP="-"
|
||||
- ninja -C build
|
||||
package:
|
||||
image: /bin/bash
|
||||
commands:
|
||||
- source cutter-deps/env.sh
|
||||
- ninja -C build package
|
||||
deploy:
|
||||
when:
|
||||
event: tag
|
||||
tag: v*
|
||||
image: /bin/bash
|
||||
commands:
|
||||
- gh release upload "${CI_COMMIT_TAG}" build/Cutter-*.dmg
|
||||
secrets: [ github_token ]
|
113
CMakeLists.txt
113
CMakeLists.txt
@ -14,8 +14,7 @@ option(CUTTER_USE_BUNDLED_RIZIN "Use rizin from ./rizin submodule instead of sea
|
||||
option(CUTTER_USE_ADDITIONAL_RIZIN_PATHS "Search rizin in additional paths which are not part of default system library paths.\
|
||||
Disable this option if you are linking against rizin pacakged as proper system library or in a custom path and additional are paths causing problems." ON)
|
||||
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_CRASH_REPORTS "Enable crash report system. Unused if CUTTER_ENABLE_CRASH_REPORTS=OFF" OFF)
|
||||
option(CUTTER_ENABLE_PYTHON_BINDINGS "Enable generating Python bindings with Shiboken. Unused if CUTTER_ENABLE_PYTHON=OFF." OFF)
|
||||
option(CUTTER_APPIMAGE_BUILD "Enable Appimage specific changes. Doesn't cause building of Appimage itself." OFF)
|
||||
tri_option(CUTTER_ENABLE_KSYNTAXHIGHLIGHTING "Use KSyntaxHighlighting" AUTO)
|
||||
tri_option(CUTTER_ENABLE_GRAPHVIZ "Enable use of graphviz for graph layout" AUTO)
|
||||
@ -23,8 +22,12 @@ set(SHIBOKEN_EXTRA_OPTIONS "" CACHE STRING "Extra options for shiboken generator
|
||||
set(CUTTER_EXTRA_PLUGIN_DIRS "" CACHE STRING "List of addition plugin locations")
|
||||
option(CUTTER_ENABLE_DEPENDENCY_DOWNLOADS "Enable downloading of dependencies. Setting to OFF doesn't affect any downloads done by rizin build." OFF)
|
||||
option(CUTTER_ENABLE_PACKAGING "Enable building platform-specific packages for distributing" OFF)
|
||||
option(CUTTER_ENABLE_SIGDB "Downloads and installs sigdb (only available when CUTTER_USE_BUNDLED_RIZIN=ON)." OFF)
|
||||
option(CUTTER_PACKAGE_DEPENDENCIES "During install step include the third party dependencies." OFF)
|
||||
option(CUTTER_PACKAGE_RZ_GHIDRA "Compile and install rz-ghidra during install step." OFF)
|
||||
option(CUTTER_PACKAGE_RZ_LIBSWIFT "Compile and install rz-libswift demangler during the install step." OFF)
|
||||
option(CUTTER_PACKAGE_RZ_LIBYARA "Compile and install rz-libyara during the install step." OFF)
|
||||
option(CUTTER_PACKAGE_RZ_SILHOUETTE "Compile and install rz-silhouette during the install step." OFF)
|
||||
option(CUTTER_PACKAGE_JSDEC "Compile and install jsdec during install step." OFF)
|
||||
OPTION(CUTTER_QT6 "Use QT6" OFF)
|
||||
|
||||
@ -33,12 +36,36 @@ if(NOT CUTTER_ENABLE_PYTHON)
|
||||
endif()
|
||||
|
||||
set(CUTTER_VERSION_MAJOR 2)
|
||||
set(CUTTER_VERSION_MINOR 0)
|
||||
set(CUTTER_VERSION_PATCH 2)
|
||||
set(CUTTER_VERSION_MINOR 2)
|
||||
set(CUTTER_VERSION_PATCH 0)
|
||||
|
||||
set(CUTTER_VERSION_FULL "${CUTTER_VERSION_MAJOR}.${CUTTER_VERSION_MINOR}.${CUTTER_VERSION_PATCH}")
|
||||
set(CUTTER_VERSION "${CUTTER_VERSION_MAJOR}.${CUTTER_VERSION_MINOR}.${CUTTER_VERSION_PATCH}")
|
||||
|
||||
project(Cutter VERSION "${CUTTER_VERSION_FULL}")
|
||||
execute_process(COMMAND git log --pretty=format:'%h' -n 1
|
||||
OUTPUT_VARIABLE GIT_REV
|
||||
ERROR_QUIET)
|
||||
|
||||
# Check whether we got any revision (which isn't
|
||||
# always the case, e.g. when someone downloaded a zip file
|
||||
if ("${GIT_REV}" STREQUAL "")
|
||||
set(CUTTER_VERSION_FULL "${CUTTER_VERSION}")
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND git rev-parse --abbrev-ref HEAD
|
||||
OUTPUT_VARIABLE GIT_BRANCH)
|
||||
string(STRIP "${GIT_REV}" GIT_REV)
|
||||
string(SUBSTRING "${GIT_REV}" 1 7 GIT_REV)
|
||||
string(STRIP "${GIT_BRANCH}" GIT_BRANCH)
|
||||
set(CUTTER_VERSION_FULL "${CUTTER_VERSION}-${GIT_BRANCH}-${GIT_REV}")
|
||||
endif()
|
||||
|
||||
project(Cutter VERSION "${CUTTER_VERSION}")
|
||||
|
||||
# Enable solution folder support
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
|
||||
# Put Qt files in a separate folder
|
||||
set_property(GLOBAL PROPERTY AUTOGEN_SOURCE_GROUP "Generated Files")
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
@ -48,24 +75,22 @@ if(CUTTER_USE_BUNDLED_RIZIN)
|
||||
include(BundledRizin)
|
||||
set(RIZIN_TARGET Rizin)
|
||||
else()
|
||||
find_package(Rizin REQUIRED)
|
||||
set(RIZIN_TARGET Rizin::librz)
|
||||
find_package(Rizin COMPONENTS Core REQUIRED)
|
||||
set(RIZIN_TARGET Rizin::Core)
|
||||
endif()
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(QT_COMPONENTS Core Widgets Gui Svg Network)
|
||||
if (CUTTER_QT6)
|
||||
set(QT_PREFIX Qt6)
|
||||
list(APPEND QT_COMPONENTS Core5Compat SvgWidgets OpenGLWidgets)
|
||||
else()
|
||||
set(QT_PREFIX Qt5)
|
||||
endif()
|
||||
|
||||
find_package(${QT_PREFIX} REQUIRED COMPONENTS Core Widgets Gui Svg Network)
|
||||
if (CUTTER_QT6)
|
||||
find_package(${QT_PREFIX} REQUIRED COMPONENTS Core5Compat SvgWidgets OpenGLWidgets)
|
||||
endif()
|
||||
find_package(${QT_PREFIX} REQUIRED COMPONENTS ${QT_COMPONENTS})
|
||||
|
||||
if(CUTTER_ENABLE_PYTHON)
|
||||
find_package(PythonInterp REQUIRED)
|
||||
@ -75,27 +100,47 @@ if(CUTTER_ENABLE_PYTHON)
|
||||
add_definitions(-DCUTTER_ENABLE_PYTHON)
|
||||
|
||||
if(CUTTER_ENABLE_PYTHON_BINDINGS)
|
||||
# 5.12.3 => 5.12
|
||||
if("${Qt5_VERSION}" MATCHES "^([0-9]+\\.[0-9]+)\\.[0-9]+")
|
||||
set(Shiboken2_VERSION_REQUIRED "${CMAKE_MATCH_1}")
|
||||
if (CUTTER_QT6)
|
||||
# 6.12.3 => 6.12
|
||||
if("${Qt6_VERSION}" MATCHES "^([0-9]+\\.[0-9]+)\\.[0-9]+")
|
||||
set(Shiboken6_VERSION_REQUIRED "${CMAKE_MATCH_1}")
|
||||
else()
|
||||
message(FATAL_ERROR "Failed to recognize Qt version")
|
||||
endif()
|
||||
find_package(Shiboken6 "${Shiboken6_VERSION_REQUIRED}" REQUIRED)
|
||||
find_package(Shiboken6Tools "${Shiboken6_VERSION_REQUIRED}" REQUIRED)
|
||||
find_package(PySide6 "${Shiboken6_VERSION_REQUIRED}" REQUIRED)
|
||||
get_target_property(LIBSHIBOKEN_INCLUDE_DIRS Shiboken6::libshiboken INTERFACE_INCLUDE_DIRECTORIES)
|
||||
get_target_property(PYSIDE_INCLUDE_DIRS PySide6::pyside6 INTERFACE_INCLUDE_DIRECTORIES)
|
||||
# Check the presence of "pysidecleanup.h"
|
||||
include(CheckIncludeFileCXX)
|
||||
set(CMAKE_REQUIRED_INCLUDES "${PYSIDE_INCLUDE_DIRS};${LIBSHIBOKEN_INCLUDE_DIRS}")
|
||||
CHECK_INCLUDE_FILE_CXX("pysidecleanup.h" HAVE_PYSIDECLEANUP)
|
||||
add_compile_definitions("HAVE_PYSIDECLEANUP=${HAVE_PYSIDECLEANUP}")
|
||||
else()
|
||||
message(FATAL_ERROR "Failed to recognize Qt version")
|
||||
# 5.12.3 => 5.12
|
||||
if("${Qt5_VERSION}" MATCHES "^([0-9]+\\.[0-9]+)\\.[0-9]+")
|
||||
set(Shiboken2_VERSION_REQUIRED "${CMAKE_MATCH_1}")
|
||||
else()
|
||||
message(FATAL_ERROR "Failed to recognize Qt version")
|
||||
endif()
|
||||
find_package(Shiboken2 "${Shiboken2_VERSION_REQUIRED}" REQUIRED)
|
||||
find_package(PySide2 "${Shiboken2_VERSION_REQUIRED}" REQUIRED)
|
||||
get_target_property(PYSIDE_INCLUDE_DIRS PySide2::pyside2 INTERFACE_INCLUDE_DIRECTORIES)
|
||||
endif()
|
||||
find_package(Shiboken2 "${Shiboken2_VERSION_REQUIRED}" REQUIRED)
|
||||
find_package(PySide2 "${Shiboken2_VERSION_REQUIRED}" REQUIRED)
|
||||
|
||||
get_target_property(PYSIDE_INCLUDE_DIR PySide2::pyside2 INTERFACE_INCLUDE_DIRECTORIES)
|
||||
list(GET PYSIDE_INCLUDE_DIR 0 PYSIDE_INCLUDE_DIR)
|
||||
include_directories(${PYSIDE_INCLUDE_DIR}
|
||||
${PYSIDE_INCLUDE_DIR}/QtCore
|
||||
${PYSIDE_INCLUDE_DIR}/QtGui
|
||||
${PYSIDE_INCLUDE_DIR}/QtWidgets)
|
||||
foreach(_dir IN LISTS PYSIDE_INCLUDE_DIRS)
|
||||
include_directories(${_dir}
|
||||
${_dir}/QtCore
|
||||
${_dir}/QtGui
|
||||
${_dir}/QtWidgets)
|
||||
endforeach()
|
||||
|
||||
add_definitions(-DCUTTER_ENABLE_PYTHON_BINDINGS)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(CUTTER_ENABLE_KSYNTAXHIGHLIGHTING)
|
||||
if(CUTTER_ENABLE_KSYNTAXHIGHLIGHTING AND (NOT CUTTER_QT6))
|
||||
if(CUTTER_ENABLE_KSYNTAXHIGHLIGHTING STREQUAL AUTO)
|
||||
find_package(KF5SyntaxHighlighting)
|
||||
if(KF5SyntaxHighlighting_FOUND)
|
||||
@ -108,6 +153,9 @@ if(CUTTER_ENABLE_KSYNTAXHIGHLIGHTING)
|
||||
set(KSYNTAXHIGHLIGHTING_STATUS ON)
|
||||
endif()
|
||||
else()
|
||||
if(CUTTER_ENABLE_KSYNTAXHIGHLIGHTING AND CUTTER_QT6)
|
||||
message(WARNING "KSyntaxHighlighting has been disabled because not supported in QT6")
|
||||
endif()
|
||||
set(KSYNTAXHIGHLIGHTING_STATUS OFF)
|
||||
endif()
|
||||
|
||||
@ -124,11 +172,22 @@ message(STATUS "")
|
||||
message(STATUS "Building Cutter version ${CUTTER_VERSION_FULL}")
|
||||
message(STATUS "Options:")
|
||||
message(STATUS "- Bundled rizin: ${CUTTER_USE_BUNDLED_RIZIN}")
|
||||
if(CUTTER_USE_BUNDLED_RIZIN)
|
||||
message(STATUS "- Bundled sigdb: ${CUTTER_ENABLE_SIGDB}")
|
||||
endif()
|
||||
message(STATUS "- Python: ${CUTTER_ENABLE_PYTHON}")
|
||||
message(STATUS "- Python Bindings: ${CUTTER_ENABLE_PYTHON_BINDINGS}")
|
||||
message(STATUS "- Crash Handling: ${CUTTER_ENABLE_CRASH_REPORTS}")
|
||||
message(STATUS "- KSyntaxHighlighting: ${KSYNTAXHIGHLIGHTING_STATUS}")
|
||||
message(STATUS "- Graphviz: ${CUTTER_ENABLE_GRAPHVIZ}")
|
||||
message(STATUS "- Downloads dependencies: ${CUTTER_ENABLE_DEPENDENCY_DOWNLOADS}")
|
||||
message(STATUS "- Enable Packaging: ${CUTTER_ENABLE_PACKAGING}")
|
||||
message(STATUS "- Package Dependencies: ${CUTTER_PACKAGE_DEPENDENCIES}")
|
||||
message(STATUS "- Package RzGhidra: ${CUTTER_PACKAGE_RZ_GHIDRA}")
|
||||
message(STATUS "- Package RzLibSwift: ${CUTTER_PACKAGE_RZ_LIBSWIFT}")
|
||||
message(STATUS "- Package RzLibYara: ${CUTTER_PACKAGE_RZ_LIBYARA}")
|
||||
message(STATUS "- Package RzSilhouette: ${CUTTER_PACKAGE_RZ_SILHOUETTE}")
|
||||
message(STATUS "- Package JSDec: ${CUTTER_PACKAGE_JSDEC}")
|
||||
message(STATUS "- QT6: ${CUTTER_QT6}")
|
||||
message(STATUS "")
|
||||
|
||||
add_subdirectory(src)
|
||||
|
@ -16,7 +16,7 @@ Please follow our contribution guidelines: https://cutter.re/docs/contributing.h
|
||||
|
||||
## Contributing to the documentation
|
||||
|
||||
The documentation is something important for newcomers. As of today the documentation can be found [here](https://cutter.re/docs/) and it stands in the [docs](https://github.com/rizinorg/cutter/tree/master/docs) folder.
|
||||
The documentation is something important for newcomers. As of today the documentation can be found [here](https://cutter.re/docs/) and it stands in the [docs](docs) folder.
|
||||
The API Reference is automatically generated from the source code, so it is strongly advised to document your code.
|
||||
Check issues marked as "Documentation" on our issues [list](https://github.com/rizinorg/cutter/issues?q=is%3Aissue+is%3Aopen+label%3ADocumentation).
|
||||
|
||||
|
13
README.md
13
README.md
@ -1,14 +1,13 @@
|
||||
<img width="150" height="150" align="left" style="float: left; margin: 0 10px 0 0;" alt="Cutter logo" src="https://raw.githubusercontent.com/rizinorg/cutter/master/src/img/cutter.svg?sanitize=true">
|
||||
<img width="150" height="150" align="left" style="float: left; margin: 0 10px 0 0;" alt="Cutter logo" src="https://raw.githubusercontent.com/rizinorg/cutter/dev/src/img/cutter.svg?sanitize=true">
|
||||
|
||||
# Cutter
|
||||
|
||||
Cutter is a free and open-source reverse engineering platform powered by [rizin](https://github.com/rizinorg/rizin). It aims at being an advanced and customizable reverse engineering platform while keeping the user experience in mind. Cutter is created by reverse engineers for reverse engineers.
|
||||
|
||||
[![Cutter CI](https://github.com/rizinorg/cutter/workflows/Cutter%20CI/badge.svg)](https://github.com/rizinorg/cutter/actions?query=workflow%3A%22Cutter+CI%22)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/tn7kttv55b8wf799/branch/master?svg=true)](https://ci.appveyor.com/project/rizinorg/cutter/branch/master)
|
||||
[![Total alerts](https://img.shields.io/lgtm/alerts/g/rizinorg/cutter.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/rizinorg/cutter/alerts/)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/tn7kttv55b8wf799/branch/dev?svg=true)](https://ci.appveyor.com/project/rizinorg/cutter/branch/dev)
|
||||
|
||||
![Screenshot](https://raw.githubusercontent.com/rizinorg/cutter/master/docs/source/images/screenshot.png)
|
||||
![Screenshot](https://raw.githubusercontent.com/rizinorg/cutter/dev/docs/source/images/screenshot.png)
|
||||
|
||||
## Learn more at [cutter.re](https://cutter.re).
|
||||
|
||||
@ -17,15 +16,17 @@ Cutter is a free and open-source reverse engineering platform powered by [rizin]
|
||||
|
||||
Cutter release binaries for all major platforms (Linux, macOS, Windows) can be downloaded from [GitHub Releases](https://github.com/rizinorg/cutter/releases).
|
||||
|
||||
- **Linux**: Download the `.AppImage` file. Then make it executable and run as below or use [AppImageLauncher](https://github.com/TheAssassin/AppImageLauncher).
|
||||
- **Linux**: If your distribution provides it, check for `cutter` package in your package manager (or `cutter-re`). If not available there, we have setup repositories in [OBS](https://openbuildservice.org/) for some common distributions. Look at [https://software.opensuse.org/package/cutter-re](https://software.opensuse.org/download/package?package=cutter-re&project=home%3ARizinOrg) and follow the instructions there. Otherwise download the `.AppImage` file from our release, make it executable and run as below or use [AppImageLauncher](https://github.com/TheAssassin/AppImageLauncher).
|
||||
|
||||
`chmod +x Cutter*.AppImage; ./Cutter*.AppImage`
|
||||
- **macOS**: Download the `.dmg` file or use [Homebrew Cask](https://github.com/Homebrew/homebrew-cask):
|
||||
|
||||
`brew install --cask cutter`
|
||||
- **Windows**: Download the `.zip` archive or use [Chocolatey](https://chocolatey.org):
|
||||
- **Windows**: Download the `.zip` archive, or use either [Chocolatey](https://chocolatey.org) or [Scoop](https://scoop.sh/):
|
||||
|
||||
`choco install cutter`
|
||||
|
||||
`scoop bucket add extras` followed by `scoop install cutter`
|
||||
|
||||
### Build from sources
|
||||
|
||||
|
@ -66,6 +66,7 @@ ForEachMacros:
|
||||
- Q_FOREVER
|
||||
- QBENCHMARK
|
||||
- QBENCHMARK_ONCE
|
||||
- CutterRzListForeach
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
|
@ -8,7 +8,7 @@ if(WIN32)
|
||||
set(RIZIN_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIG>")
|
||||
endif()
|
||||
set(RIZIN_INSTALL_BINPATH ".")
|
||||
set(MESON_OPTIONS "--prefix=${RIZIN_INSTALL_DIR}" "--bindir=${RIZIN_INSTALL_BINPATH}" "-DRZ_INCDIR=include/librz")
|
||||
set(MESON_OPTIONS "--prefix=${RIZIN_INSTALL_DIR}" "--bindir=${RIZIN_INSTALL_BINPATH}")
|
||||
else()
|
||||
set(RIZIN_INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/Rizin-prefix")
|
||||
set(MESON_OPTIONS "--prefix=${RIZIN_INSTALL_DIR}" --libdir=lib)
|
||||
@ -18,6 +18,14 @@ if (CUTTER_ENABLE_PACKAGING)
|
||||
list(APPEND MESON_OPTIONS "-Dportable=true")
|
||||
endif()
|
||||
|
||||
if (CUTTER_ENABLE_SIGDB)
|
||||
list(APPEND MESON_OPTIONS "-Dinstall_sigdb=true")
|
||||
endif()
|
||||
|
||||
if (CUTTER_PACKAGE_RZ_LIBSWIFT AND CUTTER_ENABLE_DEPENDENCY_DOWNLOADS)
|
||||
list(APPEND MESON_OPTIONS "-Duse_swift_demangler=false")
|
||||
endif()
|
||||
|
||||
find_program(MESON meson)
|
||||
if(NOT MESON)
|
||||
message(FATAL_ERROR "Failed to find meson, which is required to build bundled rizin")
|
||||
@ -32,6 +40,7 @@ ExternalProject_Add(Rizin-Bundled
|
||||
SOURCE_DIR "${RIZIN_SOURCE_DIR}"
|
||||
CONFIGURE_COMMAND "${MESON}" "<SOURCE_DIR>" ${MESON_OPTIONS} && "${MESON}" configure ${MESON_OPTIONS} --buildtype "$<$<CONFIG:Debug>:debug>$<$<NOT:$<CONFIG:Debug>>:release>"
|
||||
BUILD_COMMAND "${NINJA}"
|
||||
BUILD_ALWAYS TRUE
|
||||
INSTALL_COMMAND "${NINJA}" install)
|
||||
|
||||
set(Rizin_INCLUDE_DIRS "${RIZIN_INSTALL_DIR}/include/librz" "${RIZIN_INSTALL_DIR}/include/librz/sdb")
|
||||
@ -46,25 +55,31 @@ else()
|
||||
link_directories("${RIZIN_INSTALL_DIR}/lib")
|
||||
endif()
|
||||
|
||||
# TODO: This version number should be fetched automatically
|
||||
# instead of being hardcoded.
|
||||
set (Rizin_VERSION 0.6)
|
||||
|
||||
set (RZ_LIBS rz_core rz_config rz_cons rz_io rz_util rz_flag rz_asm rz_debug
|
||||
rz_hash rz_bin rz_lang rz_io rz_analysis rz_parse rz_bp rz_egg rz_reg
|
||||
rz_search rz_syscall rz_socket rz_magic rz_crypto rz_type rz_diff)
|
||||
rz_hash rz_bin rz_lang rz_il rz_analysis rz_parse rz_bp rz_egg rz_reg
|
||||
rz_search rz_syscall rz_socket rz_magic rz_crypto rz_type rz_diff rz_sign
|
||||
rz_demangler)
|
||||
set (RZ_EXTRA_LIBS rz_main)
|
||||
set (RZ_BIN rz-agent rz-bin rizin rz-diff rz-find rz-gg rz-hash rz-run rz-asm rz-ax)
|
||||
set (RZ_BIN rz-bin rizin rz-diff rz-find rz-gg rz-hash rz-run rz-asm rz-ax)
|
||||
|
||||
target_link_libraries(Rizin INTERFACE
|
||||
${RZ_LIBS})
|
||||
target_include_directories(Rizin INTERFACE
|
||||
"$<BUILD_INTERFACE:${Rizin_INCLUDE_DIRS}>"
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/librz>")
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/librz>"
|
||||
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/librz/sdb>")
|
||||
|
||||
install(TARGETS Rizin EXPORT CutterTargets)
|
||||
if (WIN32)
|
||||
foreach(_lib ${RZ_LIBS} ${RZ_EXTRA_LIBS})
|
||||
install(FILES "${RIZIN_INSTALL_DIR}/${RZ_INSTALL_BINPATH}/${_lib}.dll" DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
foreach(_lib ${RZ_LIBS} ${RZ_EXTRA_LIBS})
|
||||
install(FILES "${RIZIN_INSTALL_DIR}/${_lib}-${Rizin_VERSION}.dll" DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
endforeach()
|
||||
foreach(_exe ${RZ_BIN})
|
||||
install(FILES "${RIZIN_INSTALL_DIR}/${RZ_INSTALL_BINPATH}/${_exe}.exe" DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
install(FILES "${RIZIN_INSTALL_DIR}/${_exe}.exe" DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||
endforeach()
|
||||
install(DIRECTORY "${RIZIN_INSTALL_DIR}/share" DESTINATION ".")
|
||||
install(DIRECTORY "${RIZIN_INSTALL_DIR}/include" DESTINATION "."
|
||||
|
@ -1 +0,0 @@
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/CutterTargets.cmake")
|
22
cmake/CutterConfig.cmake.in
Normal file
22
cmake/CutterConfig.cmake.in
Normal file
@ -0,0 +1,22 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
set(Cutter_RIZIN_BUNDLED @CUTTER_USE_BUNDLED_RIZIN@)
|
||||
|
||||
include(CMakeFindDependencyMacro)
|
||||
find_dependency(@QT_PREFIX@ COMPONENTS @QT_COMPONENTS@)
|
||||
find_dependency(Rizin COMPONENTS Core)
|
||||
|
||||
# Make a best guess for a user location from where plugins can be loaded.
|
||||
# This can be used in Cutter plugins like
|
||||
# set(CUTTER_INSTALL_PLUGDIR "${Cutter_USER_PLUGINDIR}" CACHE STRING "Directory to install Cutter plugin into")
|
||||
# see https://doc.qt.io/qt-5/qstandardpaths.html under AppDataLocation
|
||||
if(APPLE)
|
||||
set(Cutter_USER_PLUGINDIR "$ENV{HOME}/Library/Application Support/rizin/cutter/plugins/native")
|
||||
elseif(WIN32)
|
||||
file(TO_CMAKE_PATH "$ENV{APPDATA}" Cutter_USER_PLUGINDIR)
|
||||
set(Cutter_USER_PLUGINDIR "${Cutter_USER_PLUGINDIR}/rizin/cutter/plugins/native")
|
||||
else()
|
||||
set(Cutter_USER_PLUGINDIR "$ENV{HOME}/.local/share/rizin/cutter/plugins/native")
|
||||
endif()
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/CutterTargets.cmake")
|
@ -20,4 +20,4 @@ else()
|
||||
include(GNUInstallDirs)
|
||||
set(CUTTER_INSTALL_DATADIR "${CMAKE_INSTALL_DATAROOTDIR}/${CUTTER_DIR_NAME}" CACHE PATH "Resource installation directory")
|
||||
endif()
|
||||
set(ConfigPackageLocation "${CMAKE_INSTALL_LIBDIR}/Cutter" CACHE PATH "Cmake file install location")
|
||||
set(CUTTER_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/Cutter" CACHE PATH "CMake file install location")
|
||||
|
@ -1,65 +0,0 @@
|
||||
# - Find Breakpad
|
||||
#
|
||||
# Breakpad_FOUND - True if Breakpad has been found.
|
||||
# Breakpad_INCLUDE_DIRS - Breakpad include directory
|
||||
# Breakpad_LIBRARIES - List of libraries when using Breakpad.
|
||||
|
||||
set(Breakpad_LIBRARIES_VARS "")
|
||||
if(WIN32)
|
||||
find_path(Breakpad_INCLUDE_DIRS
|
||||
client/windows/handler/exception_handler.h
|
||||
HINTS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Breakpad/src/src")
|
||||
|
||||
set(Breakpad_LIBRARY_NAMES
|
||||
exception_handler
|
||||
crash_generation_client
|
||||
common
|
||||
)
|
||||
|
||||
set(Breakpad_LIBRARIES "")
|
||||
|
||||
foreach(libname ${Breakpad_LIBRARY_NAMES})
|
||||
find_library(Breakpad_LIBRARY_${libname}
|
||||
${libname}
|
||||
HINTS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Breakpad/src/src/client/windows/Release/lib"
|
||||
REQUIRED)
|
||||
|
||||
list(APPEND Breakpad_LIBRARIES ${Breakpad_LIBRARY_${libname}})
|
||||
list(APPEND Breakpad_LIBRARIES_VARS "Breakpad_LIBRARY_${libname}")
|
||||
endforeach()
|
||||
|
||||
set (Breakpad_LINK_LIBRARIES ${Breakpad_LIBRARIES})
|
||||
|
||||
set(Breakpad_LIBRARY_DIRS "")
|
||||
elseif(APPLE)
|
||||
find_library(Breakpad_LINK_LIBRARIES Breakpad REQUIRED)
|
||||
set(Breakpad_LIBRARIES ${Breakpad_LINK_LIBRARIES})
|
||||
# Assumes Breakpad is packed as Framework
|
||||
set(Breakpad_INCLUDE_DIRS "${Breakpad_LINK_LIBRARIES}/Headers")
|
||||
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()
|
||||
|
||||
# could be simplified in > cmake 3.11 using pkg_search_module IMPORTED_TARGET [GLOBAL] but this would still be required for windows
|
||||
add_library(Breakpad::client INTERFACE IMPORTED)
|
||||
set_target_properties(Breakpad::client PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Breakpad_INCLUDE_DIRS}")
|
||||
set_target_properties(Breakpad::client PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES "${Breakpad_LINK_LIBRARIES}")
|
||||
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Breakpad REQUIRED_VARS Breakpad_LIBRARIES Breakpad_INCLUDE_DIRS ${Breakpad_LIBRARIES_VARS})
|
||||
|
||||
mark_as_advanced(Breakpad_LIBRARIES_VARS)
|
||||
|
@ -65,4 +65,4 @@ else()
|
||||
INTERFACE_LINK_LIBRARIES "${PYSIDE_LIBRARY}")
|
||||
endif()
|
||||
|
||||
mark_as_advanced(PYSIDE_INCLUDE_DIR PYSIDE_LIBRARY PYSIDE_BINARY)
|
||||
mark_as_advanced(PYSIDE_INCLUDE_DIR PYSIDE_LIBRARY PYSIDE_BINARY)
|
||||
|
68
cmake/FindPySide6.cmake
Normal file
68
cmake/FindPySide6.cmake
Normal file
@ -0,0 +1,68 @@
|
||||
|
||||
set(_module PySide6)
|
||||
|
||||
find_package(${_module} ${${_module}_FIND_VERSION} CONFIG QUIET)
|
||||
set(_lib_target ${_module}::pyside6)
|
||||
|
||||
if(NOT ${_module}_FOUND)
|
||||
include(PythonInfo)
|
||||
find_python_site_packages(PYTHON_SITE_PACKAGES)
|
||||
get_python_extension_suffix(PYTHON_EXTENSION_SUFFIX)
|
||||
|
||||
find_library(PYSIDE_LIBRARY
|
||||
NAMES
|
||||
"pyside6${PYTHON_EXTENSION_SUFFIX}"
|
||||
"pyside6${PYTHON_EXTENSION_SUFFIX}.${${_module}_FIND_VERSION_MAJOR}.${${_module}_FIND_VERSION_MINOR}"
|
||||
PATH_SUFFIXES "${PYTHON_SITE_PACKAGES}/PySide6")
|
||||
|
||||
find_path(PYSIDE_INCLUDE_DIR
|
||||
pyside.h
|
||||
PATH_SUFFIXES "${PYTHON_SITE_PACKAGES}/PySide6/include")
|
||||
|
||||
find_path(PYSIDE_TYPESYSTEMS
|
||||
typesystem_core.xml
|
||||
PATH_SUFFIXES "${PYTHON_SITE_PACKAGES}/PySide6/typesystems")
|
||||
endif()
|
||||
|
||||
if(TARGET ${_lib_target})
|
||||
get_target_property(_is_imported ${_lib_target} IMPORTED)
|
||||
if(_is_imported)
|
||||
get_target_property(_imported_location ${_lib_target} IMPORTED_LOCATION)
|
||||
if(NOT _imported_location)
|
||||
message(STATUS "Target ${_lib_target} does not specify its IMPORTED_LOCATION! Trying to find it ourselves...")
|
||||
set(_find_args)
|
||||
if(${_module}_CONFIG)
|
||||
get_filename_component(_pyside6_lib_dir "${${_module}_CONFIG}/../../../" ABSOLUTE)
|
||||
set(_find_args PATHS "${_pyside6_lib_dir}")
|
||||
endif()
|
||||
find_library(PYSIDE_LIBRARY
|
||||
NAMES
|
||||
"pyside6${PYTHON_CONFIG_SUFFIX}"
|
||||
"pyside6${PYTHON_CONFIG_SUFFIX}.${${_module}_FIND_VERSION_MAJOR}.${${_module}_FIND_VERSION_MINOR}"
|
||||
${_find_args})
|
||||
if(NOT PYSIDE_LIBRARY)
|
||||
set(_message_type WARNING)
|
||||
if(${_module}_FIND_REQUIRED)
|
||||
set(_message_type FATAL_ERROR)
|
||||
endif()
|
||||
message(${_message_type} "Failed to manually find library for ${_module}")
|
||||
return()
|
||||
endif()
|
||||
message(STATUS "IMPORTED_LOCATION for ${_lib_target} found: ${PYSIDE_LIBRARY}")
|
||||
set_target_properties(${_lib_target} PROPERTIES IMPORTED_LOCATION "${PYSIDE_LIBRARY}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(${_module}
|
||||
FOUND_VAR ${_module}_FOUND
|
||||
REQUIRED_VARS PYSIDE_LIBRARY PYSIDE_INCLUDE_DIR PYSIDE_TYPESYSTEMS
|
||||
VERSION_VAR ${_module}_VERSION)
|
||||
|
||||
add_library(${_module}::pyside6 INTERFACE IMPORTED)
|
||||
set_target_properties(${_module}::pyside6 PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${PYSIDE_INCLUDE_DIR}"
|
||||
INTERFACE_LINK_LIBRARIES "${PYSIDE_LIBRARY}")
|
||||
endif()
|
||||
|
||||
mark_as_advanced(PYSIDE_INCLUDE_DIR PYSIDE_LIBRARY PYSIDE_BINARY)
|
@ -1,117 +0,0 @@
|
||||
# - Find Rizin (librz)
|
||||
#
|
||||
# This module provides the following imported targets, if found:
|
||||
#
|
||||
# Rizin::librz
|
||||
#
|
||||
# This will define the following variables:
|
||||
# (but don't use them if you don't know what you are doing, use Rizin::librz)
|
||||
#
|
||||
# Rizin_FOUND - True if librz has been found.
|
||||
# Rizin_INCLUDE_DIRS - librz include directory
|
||||
# Rizin_LIBRARIES - List of libraries when using librz.
|
||||
# Rizin_LIBRARY_DIRS - librz library directories
|
||||
#
|
||||
# If librz was found using find_library and not pkg-config, the following variables will also be set:
|
||||
# Rizin_LIBRARY_<name> - Path to library rz_<name>
|
||||
|
||||
if(WIN32)
|
||||
find_path(Rizin_INCLUDE_DIRS
|
||||
NAMES rz_core.h rz_bin.h rz_util.h
|
||||
HINTS
|
||||
"$ENV{HOME}/bin/prefix/rizin/include/librz"
|
||||
/usr/local/include/libr
|
||||
/usr/include/librz)
|
||||
find_path(SDB_INCLUDE_DIR
|
||||
NAMES sdb.h sdbht.h sdb_version.h
|
||||
HINTS
|
||||
"$ENV{HOME}/bin/prefix/rizin/include/librz/sdb"
|
||||
/usr/local/include/librz/sdb
|
||||
/usr/include/librz/sdb)
|
||||
|
||||
list(APPEND Rizin_INCLUDE_DIRS ${SDB_INCLUDE_DIR})
|
||||
|
||||
set(Rizin_LIBRARY_NAMES
|
||||
core
|
||||
config
|
||||
cons
|
||||
io
|
||||
util
|
||||
flag
|
||||
asm
|
||||
debug
|
||||
hash
|
||||
bin
|
||||
lang
|
||||
io
|
||||
analysis
|
||||
parse
|
||||
bp
|
||||
egg
|
||||
reg
|
||||
search
|
||||
syscall
|
||||
socket
|
||||
magic
|
||||
crypto
|
||||
type)
|
||||
|
||||
set(Rizin_LIBRARIES "")
|
||||
set(Rizin_LIBRARIES_VARS "")
|
||||
foreach(libname ${Rizin_LIBRARY_NAMES})
|
||||
find_library(Rizin_LIBRARY_${libname}
|
||||
rz_${libname}
|
||||
HINTS
|
||||
"$ENV{HOME}/bin/prefix/rizin/lib"
|
||||
/usr/local/lib
|
||||
/usr/lib)
|
||||
|
||||
list(APPEND Rizin_LIBRARIES ${Rizin_LIBRARY_${libname}})
|
||||
list(APPEND Rizin_LIBRARIES_VARS "Rizin_LIBRARY_${libname}")
|
||||
endforeach()
|
||||
|
||||
set(Rizin_LIBRARY_DIRS "")
|
||||
|
||||
add_library(Rizin::librz UNKNOWN IMPORTED)
|
||||
set_target_properties(Rizin::librz PROPERTIES
|
||||
IMPORTED_LOCATION "${Rizin_LIBRARY_core}"
|
||||
IMPORTED_LINK_INTERFACE_LIBRARIES "${Rizin_LIBRARIES}"
|
||||
INTERFACE_LINK_DIRECTORIES "${Rizin_LIBRARY_DIRS}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Rizin_INCLUDE_DIRS}")
|
||||
set(Rizin_TARGET Rizin::librz)
|
||||
else()
|
||||
# support installation locations used by rizin scripts like sys/user.sh and sys/install.sh
|
||||
if(CUTTER_USE_ADDITIONAL_RIZIN_PATHS)
|
||||
set(Rizin_CMAKE_PREFIX_PATH_TEMP ${CMAKE_PREFIX_PATH})
|
||||
list(APPEND CMAKE_PREFIX_PATH "$ENV{HOME}/bin/prefix/rizin") # sys/user.sh
|
||||
list(APPEND CMAKE_PREFIX_PATH "/usr/local") # sys/install.sh
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
if(CMAKE_VERSION VERSION_LESS "3.6")
|
||||
pkg_search_module(Rizin REQUIRED rz_core)
|
||||
else()
|
||||
pkg_search_module(Rizin IMPORTED_TARGET REQUIRED rz_core)
|
||||
endif()
|
||||
|
||||
# reset CMAKE_PREFIX_PATH
|
||||
if(CUTTER_USE_ADDITIONAL_RIZIN_PATHS)
|
||||
set(CMAKE_PREFIX_PATH ${Rizin_CMAKE_PREFIX_PATH_TEMP})
|
||||
endif()
|
||||
|
||||
if((TARGET PkgConfig::Rizin) AND (NOT CMAKE_VERSION VERSION_LESS "3.11.0"))
|
||||
set_target_properties(PkgConfig::Rizin PROPERTIES IMPORTED_GLOBAL ON)
|
||||
add_library(Rizin::librz ALIAS PkgConfig::Rizin)
|
||||
set(Rizin_TARGET Rizin::librz)
|
||||
elseif(Rizin_FOUND)
|
||||
add_library(Rizin::librz INTERFACE IMPORTED)
|
||||
set_target_properties(Rizin::librz PROPERTIES
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${Rizin_INCLUDE_DIRS}")
|
||||
set_target_properties(Rizin::librz PROPERTIES
|
||||
INTERFACE_LINK_LIBRARIES "${Rizin_LIBRARIES}")
|
||||
set(Rizin_TARGET Rizin::librz)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Rizin REQUIRED_VARS Rizin_TARGET Rizin_LIBRARIES Rizin_INCLUDE_DIRS)
|
120
dist/CMakeLists.txt
vendored
120
dist/CMakeLists.txt
vendored
@ -7,7 +7,7 @@ unset(RZ_GHIDRA_PREFIX_PATH)
|
||||
|
||||
if(WIN32)
|
||||
set(CPACK_GENERATOR "ZIP")
|
||||
set(RIZIN_INSTALL_PLUGDIR "lib/plugins")
|
||||
set(RIZIN_INSTALL_PLUGDIR "lib/rizin/plugins")
|
||||
|
||||
if (CUTTER_PACKAGE_DEPENDENCIES)
|
||||
if (CUTTER_ENABLE_PYTHON)
|
||||
@ -28,7 +28,46 @@ if(WIN32)
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
RESULT_VARIABLE SCRIPT_RESULT)
|
||||
if (SCRIPT_RESULT)
|
||||
message(FATAL_ERROR \"Failed to package jsdec\")
|
||||
message(FATAL_ERROR \"Failed to package jsdec (returned \${SCRIPT_RESULT})\")
|
||||
endif()
|
||||
")
|
||||
endif()
|
||||
if (CUTTER_PACKAGE_RZ_LIBSWIFT AND CUTTER_ENABLE_DEPENDENCY_DOWNLOADS)
|
||||
install(CODE "
|
||||
set(ENV{RZ_PREFIX} \"\${CMAKE_INSTALL_PREFIX}\")
|
||||
set(ENV{PATH} \"\${CMAKE_INSTALL_PREFIX};\$ENV{PATH}\")
|
||||
execute_process(COMMAND powershell \"${CMAKE_CURRENT_SOURCE_DIR}/bundle_rz_libswift.ps1\" \"\${CMAKE_INSTALL_PREFIX}\"
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
RESULT_VARIABLE SCRIPT_RESULT)
|
||||
if (SCRIPT_RESULT)
|
||||
message(FATAL_ERROR \"Failed to package rz-libswift (returned \${SCRIPT_RESULT})\")
|
||||
endif()
|
||||
")
|
||||
endif()
|
||||
if (CUTTER_PACKAGE_RZ_LIBYARA AND CUTTER_ENABLE_DEPENDENCY_DOWNLOADS)
|
||||
install(CODE "
|
||||
set(ENV{RZ_PREFIX} \"\${CMAKE_INSTALL_PREFIX}\")
|
||||
set(ENV{PATH} \"\${CMAKE_INSTALL_PREFIX};\$ENV{PATH}\")
|
||||
execute_process(COMMAND powershell
|
||||
\"${CMAKE_CURRENT_SOURCE_DIR}/bundle_rz_libyara.ps1\"
|
||||
\"\${CMAKE_INSTALL_PREFIX}\"
|
||||
\"-DCUTTER_INSTALL_PLUGDIR=plugins/native\"
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
RESULT_VARIABLE SCRIPT_RESULT)
|
||||
if (SCRIPT_RESULT)
|
||||
message(FATAL_ERROR \"Failed to package rz_libyara (returned \${SCRIPT_RESULT})\")
|
||||
endif()
|
||||
")
|
||||
endif()
|
||||
if (CUTTER_PACKAGE_RZ_SILHOUETTE AND CUTTER_ENABLE_DEPENDENCY_DOWNLOADS)
|
||||
install(CODE "
|
||||
set(ENV{RZ_PREFIX} \"\${CMAKE_INSTALL_PREFIX}\")
|
||||
set(ENV{PATH} \"\${CMAKE_INSTALL_PREFIX};\$ENV{PATH}\")
|
||||
execute_process(COMMAND powershell \"${CMAKE_CURRENT_SOURCE_DIR}/bundle_rz_silhouette.ps1\" \"\${CMAKE_INSTALL_PREFIX}\"
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
RESULT_VARIABLE SCRIPT_RESULT)
|
||||
if (SCRIPT_RESULT)
|
||||
message(FATAL_ERROR \"Failed to package rz-silhouette (returned \${SCRIPT_RESULT})\")
|
||||
endif()
|
||||
")
|
||||
endif()
|
||||
@ -50,10 +89,6 @@ if(APPLE)
|
||||
set(CPACK_DMG_VOLUME_NAME "Cutter")
|
||||
set(CPACK_BUNDLE_APPLE_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/macos/Entitlements.plist")
|
||||
set(CPACK_APPLE_BUNDLE_ID "re.rizin.cutter")
|
||||
if (CUTTER_ENABLE_CRASH_REPORTS)
|
||||
list(APPEND CPACK_BUNDLE_APPLE_CODESIGN_FILES "/Contents/Frameworks/Breakpad.framework/Versions/Current/Resources/breakpadUtilities.dylib")
|
||||
endif()
|
||||
|
||||
|
||||
find_program(MACDEPLOYQT_PATH macdeployqt HINTS "${Qt5_DIR}/../../../bin")
|
||||
if(NOT MACDEPLOYQT_PATH)
|
||||
@ -80,21 +115,65 @@ if(APPLE)
|
||||
|
||||
get_filename_component(QT_PREFIX "${MACDEPLOYQT_PATH}/../.." ABSOLUTE)
|
||||
list(APPEND RZ_GHIDRA_PREFIX_PATH "${QT_PREFIX}")
|
||||
set(RIZIN_INSTALL_PLUGDIR "share/rizin/plugins") # escaped backslash on purpose, should be evaluated later
|
||||
set(RIZIN_INSTALL_PLUGDIR "lib/rizin/plugins") # escaped backslash on purpose, should be evaluated later
|
||||
endif()
|
||||
|
||||
if (CUTTER_PACKAGE_JSDEC AND CUTTER_ENABLE_DEPENDENCY_DOWNLOADS)
|
||||
################################################
|
||||
# macOS + Linux
|
||||
################################################
|
||||
|
||||
if(CUTTER_ENABLE_DEPENDENCY_DOWNLOADS AND (NOT WIN32))
|
||||
if (CUTTER_PACKAGE_JSDEC)
|
||||
install(CODE "
|
||||
execute_process(COMMAND \"${CMAKE_CURRENT_SOURCE_DIR}/../scripts/jsdec.sh\" --prefix=\${CMAKE_INSTALL_PREFIX}
|
||||
\"-Drizin_incdir=\${CMAKE_INSTALL_PREFIX}/include/librz\"
|
||||
\"-Drizin_libdir=\${CMAKE_INSTALL_PREFIX}/lib\"
|
||||
execute_process(COMMAND \"${CMAKE_CURRENT_SOURCE_DIR}/../scripts/jsdec.sh\"
|
||||
--pkg-config-path=\${CMAKE_INSTALL_PREFIX}/lib/pkgconfig --prefix=\${CMAKE_INSTALL_PREFIX}
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
RESULT_VARIABLE SCRIPT_RESULT)
|
||||
if (SCRIPT_RESULT)
|
||||
message(FATAL_ERROR \"Failed to package jsdec\")
|
||||
message(FATAL_ERROR \"Failed to package jsdec (returned \${SCRIPT_RESULT})\")
|
||||
endif()
|
||||
")
|
||||
endif()
|
||||
if (CUTTER_PACKAGE_RZ_LIBSWIFT)
|
||||
install(CODE "
|
||||
execute_process(COMMAND \"${CMAKE_CURRENT_SOURCE_DIR}/../scripts/rz-libswift.sh\"
|
||||
--pkg-config-path=\${CMAKE_INSTALL_PREFIX}/lib/pkgconfig --prefix=\${CMAKE_INSTALL_PREFIX}
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
RESULT_VARIABLE SCRIPT_RESULT)
|
||||
if (SCRIPT_RESULT)
|
||||
message(FATAL_ERROR \"Failed to package rz-libswift (returned \${SCRIPT_RESULT})\")
|
||||
endif()
|
||||
")
|
||||
endif()
|
||||
if (CUTTER_PACKAGE_RZ_LIBYARA)
|
||||
if(APPLE)
|
||||
set (YARA_PLUGIN_OPTIONS "-DCUTTER_INSTALL_PLUGDIR=plugins/native")
|
||||
else()
|
||||
set (YARA_PLUGIN_OPTIONS "")
|
||||
endif()
|
||||
install(CODE "
|
||||
execute_process(COMMAND
|
||||
\"${CMAKE_CURRENT_SOURCE_DIR}/../scripts/rz-libyara.sh\"
|
||||
\"\${CMAKE_INSTALL_PREFIX}\" \"${YARA_PLUGIN_OPTIONS}\"
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
RESULT_VARIABLE SCRIPT_RESULT)
|
||||
if (SCRIPT_RESULT)
|
||||
message(FATAL_ERROR \"Failed to package rz-libyara (returned \${SCRIPT_RESULT})\")
|
||||
endif()
|
||||
")
|
||||
endif()
|
||||
if (CUTTER_PACKAGE_RZ_SILHOUETTE)
|
||||
install(CODE "
|
||||
execute_process(COMMAND
|
||||
\"${CMAKE_CURRENT_SOURCE_DIR}/../scripts/rz-silhouette.sh\"
|
||||
\"\${CMAKE_INSTALL_PREFIX}\" \"${YARA_PLUGIN_OPTIONS}\"
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
RESULT_VARIABLE SCRIPT_RESULT)
|
||||
if (SCRIPT_RESULT)
|
||||
message(FATAL_ERROR \"Failed to package rz-silhouette (returned \${SCRIPT_RESULT})\")
|
||||
endif()
|
||||
")
|
||||
endif()
|
||||
|
||||
endif()
|
||||
|
||||
################################################
|
||||
@ -109,7 +188,8 @@ if(CUTTER_PACKAGE_RZ_GHIDRA)
|
||||
# installed Cutter.
|
||||
ExternalProject_Add(rz-ghidra
|
||||
GIT_REPOSITORY https://github.com/rizinorg/rz-ghidra
|
||||
#GIT_TAG v0.2.0
|
||||
#GIT_TAG v0.3.0
|
||||
#GIT_TAG c7a50a2e7c0a95cd52b167c9ee0fa1805223f08e
|
||||
GIT_TAG dev
|
||||
#GIT_SHALLOW ON # disable this line when using commit hash
|
||||
CONFIGURE_COMMAND ""
|
||||
@ -117,16 +197,12 @@ if(CUTTER_PACKAGE_RZ_GHIDRA)
|
||||
INSTALL_COMMAND ""
|
||||
)
|
||||
endif()
|
||||
if (WIN32)
|
||||
set (GHIDRA_OPTIONS "
|
||||
\"-DRIZIN_INSTALL_PLUGDIR=\${CMAKE_INSTALL_PREFIX}/${RIZIN_INSTALL_PLUGDIR}\"
|
||||
-DCUTTER_INSTALL_PLUGDIR=plugins/native")
|
||||
elseif (APPLE)
|
||||
if (WIN32 OR APPLE)
|
||||
set (GHIDRA_OPTIONS "
|
||||
\"-DRIZIN_INSTALL_PLUGDIR=\${CMAKE_INSTALL_PREFIX}/${RIZIN_INSTALL_PLUGDIR}\"
|
||||
-DCUTTER_INSTALL_PLUGDIR=plugins/native")
|
||||
else()
|
||||
set (GHIDRA_OPTIONS "")
|
||||
set (GHIDRA_OPTIONS "-DCUTTER_INSTALL_PLUGDIR=\${CMAKE_INSTALL_PREFIX}/share/rizin/cutter/plugins/native")
|
||||
endif()
|
||||
install(CODE "
|
||||
execute_process(
|
||||
@ -143,14 +219,14 @@ if(CUTTER_PACKAGE_RZ_GHIDRA)
|
||||
-G Ninja
|
||||
)
|
||||
if (SCRIPT_RESULT)
|
||||
message(FATAL_ERROR \"Failed to configure rz-ghidra\")
|
||||
message(FATAL_ERROR \"Failed to configure rz-ghidra (returned \${SCRIPT_RESULT})\")
|
||||
endif()
|
||||
execute_process(WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/rz-ghidra-prefix/src/rz-ghidra-build
|
||||
RESULT_VARIABLE SCRIPT_RESULT
|
||||
COMMAND \${CMAKE_COMMAND} --build . --target install
|
||||
)
|
||||
if (SCRIPT_RESULT)
|
||||
message(FATAL_ERROR \"Failed to install rz-ghidra plugin\")
|
||||
message(FATAL_ERROR \"Failed to install rz-ghidra plugin (returned \${SCRIPT_RESULT})\")
|
||||
endif()
|
||||
")
|
||||
endif()
|
||||
|
12
dist/MacOSSetupBundle.cmake.in
vendored
12
dist/MacOSSetupBundle.cmake.in
vendored
@ -3,8 +3,6 @@ include(BundleUtilities)
|
||||
set(MACDEPLOYQT_PATH "@MACDEPLOYQT_PATH@")
|
||||
set(INFO_PLIST_PATH "@CPACK_BUNDLE_PLIST@")
|
||||
set(ADJUST_RIZIN_LIBS "@ADJUST_RIZIN_LIBS@")
|
||||
set(CUTTER_ENABLE_CRASH_REPORTS "@CUTTER_ENABLE_CRASH_REPORTS@")
|
||||
set(Breakpad_LINK_LIBRARIES "@Breakpad_LINK_LIBRARIES@")
|
||||
set(CUTTER_PACKAGE_DEPENDENCIES "@CUTTER_PACKAGE_DEPENDENCIES@")
|
||||
set(CUTTER_ENABLE_PYTHON "@CUTTER_ENABLE_PYTHON@")
|
||||
|
||||
@ -25,7 +23,6 @@ file(COPY "${INFO_PLIST_PATH}" DESTINATION "${BUNDLE_PATH}/Contents")
|
||||
|
||||
# replace absolute path from build directory in rizin pkgconfig files with relative ones
|
||||
file(GLOB RZ_PCFILES "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig/rz_*.pc")
|
||||
list(APPEND RZ_PCFILES "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig/librz.pc")
|
||||
foreach (_pcfile ${RZ_PCFILES})
|
||||
file(READ "${_pcfile}" _text)
|
||||
string(REGEX REPLACE "^prefix=[^\n]*\n" "prefix=\${pcfiledir}/../..\n" _text "${_text}")
|
||||
@ -61,6 +58,9 @@ run_or_die(COMMAND install_name_tool
|
||||
run_or_die(COMMAND install_name_tool
|
||||
-add_rpath "@executable_path/../Resources/lib"
|
||||
"${EXECUTABLE_DIR}/cutter")
|
||||
run_or_die(COMMAND install_name_tool
|
||||
-add_rpath "@executable_path/../Resources/lib/rizin/plugins"
|
||||
"${EXECUTABLE_DIR}/cutter")
|
||||
|
||||
set(MACDEPLOYQT_COMMAND "${MACDEPLOYQT_PATH}" "${BUNDLE_PATH}" "-verbose=2" "-libpath=${CMAKE_INSTALL_PREFIX}/lib")
|
||||
message("Running macdeployqt \"${MACDEPLOYQT_COMMAND}\"")
|
||||
@ -80,9 +80,3 @@ foreach(_lib ${ADJUST_RIZIN_LIBS})
|
||||
get_filename_component(_name "${_lib}" NAME)
|
||||
file(REMOVE "${BUNDLE_PATH}/Contents/Frameworks/${_name}")
|
||||
endforeach()
|
||||
|
||||
if (CUTTER_ENABLE_CRASH_REPORTS)
|
||||
message("Copying Breakpad ${Breakpad_LINK_LIBRARIES}")
|
||||
set(_breakpad_lib "Versions/A/Breakpad")
|
||||
copy_resolved_framework_into_bundle("${Breakpad_LINK_LIBRARIES}/${_breakpad_lib}" "${FRAMEWORK_DIR}/Breakpad.framework/${_breakpad_lib}")
|
||||
endif()
|
||||
|
13
dist/bundle_jsdec.ps1
vendored
13
dist/bundle_jsdec.ps1
vendored
@ -2,9 +2,16 @@ $dist = $args[0]
|
||||
$python = Split-Path((Get-Command python.exe).Path)
|
||||
|
||||
if (-not (Test-Path -Path 'jsdec' -PathType Container)) {
|
||||
git clone https://github.com/rizinorg/jsdec.git --branch v0.2.x --depth 1
|
||||
git clone https://github.com/rizinorg/jsdec.git --depth 1 --branch master
|
||||
}
|
||||
cd jsdec
|
||||
& meson.exe --buildtype=release -Dc_args=-DDUK_USE_DATE_NOW_WINDOWS --prefix=$dist --libdir=lib\plugins --datadir=lib\plugins p build
|
||||
& meson.exe --buildtype=release -Dc_args=-DDUK_USE_DATE_NOW_WINDOWS -Djsc_folder=".." --prefix="$dist" p build
|
||||
ninja -C build install
|
||||
Remove-Item -Recurse -Force $dist\lib\plugins\core_pdd.lib
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$pathdll = "$dist\lib\rizin\plugins\core_pdd.dll"
|
||||
if(![System.IO.File]::Exists($pathdll)) {
|
||||
type build\meson-logs\meson-log.txt
|
||||
ls "$dist\lib\rizin\plugins\"
|
||||
throw (New-Object System.IO.FileNotFoundException("File not found: $pathdll", $pathdll))
|
||||
}
|
||||
Remove-Item -Recurse -Force "$dist\lib\rizin\plugins\core_pdd.lib"
|
||||
|
2
dist/bundle_python.ps1
vendored
2
dist/bundle_python.ps1
vendored
@ -2,7 +2,7 @@ $arch = $args[0]
|
||||
$dist = $args[1]
|
||||
|
||||
$py_version = (python --version).Split()[1]
|
||||
$py_base = "python" + $py_version[0] + $py_version[2]
|
||||
$py_base = "python" + $py_version.Split('.')[0] + $py_version.Split('.')[1]
|
||||
$py_platform = If ($arch -eq "x64") {"amd64"} Else {"win32"}
|
||||
$py_url = "https://www.python.org/ftp/python/${py_version}/python-${py_version}-embed-${py_platform}.zip"
|
||||
|
||||
|
16
dist/bundle_rz_libswift.ps1
vendored
Normal file
16
dist/bundle_rz_libswift.ps1
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
$dist = $args[0]
|
||||
$python = Split-Path((Get-Command python.exe).Path)
|
||||
|
||||
if (-not (Test-Path -Path 'libswift' -PathType Container)) {
|
||||
git clone https://github.com/rizinorg/rz-libswift.git --depth 1 libswift
|
||||
}
|
||||
cd libswift
|
||||
& meson.exe --buildtype=release --prefix=$dist build
|
||||
ninja -C build install
|
||||
$pathdll = "$dist\lib\rizin\plugins\swift.dll"
|
||||
if(![System.IO.File]::Exists($pathdll)) {
|
||||
type build/meson-logs/meson-log.txt
|
||||
ls "$dist\lib\rizin\plugins\"
|
||||
throw (New-Object System.IO.FileNotFoundException("File not found: $pathdll", $pathdll))
|
||||
}
|
||||
Remove-Item -Recurse -Force "$dist\lib\rizin\plugins\swift.lib"
|
26
dist/bundle_rz_libyara.ps1
vendored
Normal file
26
dist/bundle_rz_libyara.ps1
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
$dist = $args[0]
|
||||
$cmake_opts = $args[1]
|
||||
$python = Split-Path((Get-Command python.exe).Path)
|
||||
|
||||
if (-not (Test-Path -Path 'rz_libyara' -PathType Container)) {
|
||||
git clone https://github.com/rizinorg/rz-libyara.git --depth 1 rz_libyara
|
||||
git -C rz_libyara submodule init
|
||||
git -C rz_libyara submodule update
|
||||
}
|
||||
cd rz_libyara
|
||||
& meson.exe --buildtype=release --prefix=$dist -Duse_sys_yara=disabled -Denable_openssl=false build
|
||||
ninja -C build install
|
||||
$pathdll = "$dist\lib\rizin\plugins\rz_yara.dll"
|
||||
if(![System.IO.File]::Exists($pathdll)) {
|
||||
type build/meson-logs/meson-log.txt
|
||||
ls "$dist\lib\rizin\plugins\"
|
||||
throw (New-Object System.IO.FileNotFoundException("File not found: $pathdll", $pathdll))
|
||||
}
|
||||
Remove-Item -Recurse -Force "$dist\lib\rizin\plugins\rz_yara.lib"
|
||||
|
||||
cd cutter-plugin
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DRIZIN_INSTALL_PLUGDIR="../build" -DCMAKE_INSTALL_PREFIX="$dist" $cmake_opts ..
|
||||
ninja
|
||||
ninja install
|
17
dist/bundle_rz_silhouette.ps1
vendored
Normal file
17
dist/bundle_rz_silhouette.ps1
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
$dist = $args[0]
|
||||
$cmake_opts = $args[1]
|
||||
$python = Split-Path((Get-Command python.exe).Path)
|
||||
|
||||
if (-not (Test-Path -Path 'rz-silhouette' -PathType Container)) {
|
||||
git clone https://github.com/rizinorg/rz-silhouette.git --depth 1 rz-silhouette
|
||||
}
|
||||
cd rz-silhouette
|
||||
& meson.exe --buildtype=release --prefix=$dist build
|
||||
ninja -C build install
|
||||
$pathdll = "$dist\lib\rizin\plugins\rz_silhouette.dll"
|
||||
if(![System.IO.File]::Exists($pathdll)) {
|
||||
type build/meson-logs/meson-log.txt
|
||||
ls "$dist\lib\rizin\plugins\"
|
||||
throw (New-Object System.IO.FileNotFoundException("File not found: $pathdll", $pathdll))
|
||||
}
|
||||
Remove-Item -Recurse -Force "$dist\lib\rizin\plugins\rz_silhouette.lib"
|
4
dist/macos/Info.plist.in
vendored
4
dist/macos/Info.plist.in
vendored
@ -7,9 +7,9 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>cutter</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@FULL_VERSION@</string>
|
||||
<string>@CUTTER_VERSION_FULL@</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@FULL_VERSION@</string>
|
||||
<string>@CUTTER_VERSION_FULL@</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Licensed under the GPLv3 by the Cutter developers.</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
|
@ -6,7 +6,7 @@ Building
|
||||
If you just want to use the latest Release version of Cutter, please note
|
||||
that we provide pre-compiled binaries for Windows, Linux, and macOS on
|
||||
our `release page <https://github.com/rizinorg/cutter/releases/latest>`_ and
|
||||
`CI page <https://nightly.link/rizinorg/cutter/workflows/ccpp/master>`_ for latest development builds.
|
||||
`CI page <https://nightly.link/rizinorg/cutter/workflows/ccpp/dev>`_ for latest development builds.
|
||||
|
||||
This page describes how to do a basic build from the command line. If you are planning to modify Cutter it is recommended to also read our :doc:`development environment setup</contributing/code/ide-setup>`.
|
||||
|
||||
@ -64,7 +64,22 @@ On Debian-based Linux distributions, all of these essential packages can be inst
|
||||
sudo apt install build-essential cmake meson libzip-dev zlib1g-dev qt5-default libqt5svg5-dev qttools5-dev qttools5-dev-tools
|
||||
|
||||
.. note::
|
||||
For Ubuntu 18.04 and lower, ``meson`` should be installed with ``pip install --upgrade --user meson``.
|
||||
On Debian 11 (bullseye) and higher or Ubuntu 22.04 (Jammy) and higher, replace ``qt5-default`` above with ``qtbase5-dev``.
|
||||
|
||||
Depending on your configuration you'll might also need the following:
|
||||
|
||||
::
|
||||
|
||||
# When building with CUTTER_ENABLE_KSYNTAXHIGHLIGHTING (Default)
|
||||
sudo apt install libkf5syntaxhighlighting-dev
|
||||
# When building with CUTTER_ENABLE_GRAPHVIZ (Default)
|
||||
sudo apt install libgraphviz-dev
|
||||
# when building with CUTTER_ENABLE_PYTHON_BINDINGS
|
||||
sudo apt install libshiboken2-dev libpyside2-dev qtdeclarative5-dev
|
||||
|
||||
|
||||
.. note::
|
||||
For Ubuntu 20.04 and lower (or in any case you get an error ``Meson version is x but project requires >=y``), ``meson`` should be installed with ``pip install --upgrade --user meson``.
|
||||
|
||||
On Arch-based Linux distributions:
|
||||
|
||||
@ -72,6 +87,12 @@ On Arch-based Linux distributions:
|
||||
|
||||
sudo pacman -Syu --needed base-devel cmake meson qt5-base qt5-svg qt5-tools
|
||||
|
||||
On dnf/yum based distributions:
|
||||
|
||||
::
|
||||
|
||||
sudo dnf install -y gcc gcc-c++ make cmake meson qt5-qtbase-devel qt5-qtsvg-devel qt5-qttools-devel
|
||||
|
||||
Building Steps
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
@ -95,8 +116,7 @@ If you want to use Cutter with another version of Rizin you can set ``-DCUTTER_U
|
||||
.. note::
|
||||
|
||||
If you are interested in building Cutter with support for Python plugins,
|
||||
Syntax Highlighting, Crash Reporting and more,
|
||||
please look at the full list of `CMake Building Options`_.
|
||||
Syntax Highlighting and more, please look at the full list of `CMake Building Options`_.
|
||||
|
||||
|
||||
After the build process is complete, you should have the ``Cutter`` executable in the **build** dir.
|
||||
@ -215,7 +235,7 @@ Recommended Way for dev builds
|
||||
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_PREFIX_PATH=/local/opt/qt5
|
||||
cmake .. -DCMAKE_PREFIX_PATH=/usr/local/opt/qt5
|
||||
make
|
||||
|
||||
--------------
|
||||
@ -227,14 +247,13 @@ Note that there are some major building options available:
|
||||
|
||||
* ``CUTTER_USE_BUNDLED_RIZIN`` automatically compile Rizin from submodule (Enabled by default).
|
||||
* ``CUTTER_ENABLE_PYTHON`` compile with Python support.
|
||||
* ``CUTTER_ENABLE_PYTHON_BINDINGS`` automatically generate Python Bindings with Shiboken2, required for Python plugins!
|
||||
* ``CUTTER_ENABLE_PYTHON_BINDINGS`` automatically generate Python Bindings with Shiboken, required for Python plugins!
|
||||
* ``CUTTER_ENABLE_KSYNTAXHIGHLIGHTING`` use KSyntaxHighlighting for code highlighting.
|
||||
* ``CUTTER_ENABLE_GRAPHVIZ`` enable Graphviz for graph layouts.
|
||||
* ``CUTTER_EXTRA_PLUGIN_DIRS`` List of addition plugin locations. Useful when preparing package for Linux distros that have strict package layout rules.
|
||||
|
||||
Cutter binary release options, not needed for most users and might not work easily outside CI environment:
|
||||
|
||||
* ``CUTTER_ENABLE_CRASH_REPORTS`` is used to compile Cutter with crash handling system enabled (Breakpad).
|
||||
* ``CUTTER_ENABLE_DEPENDENCY_DOWNLOADS`` Enable downloading of dependencies. Setting to OFF doesn't affect any downloads done by Rizin build. This option is used for preparing Cutter binary release packges. Turned off by default.
|
||||
* ``CUTTER_PACKAGE_DEPENDENCIES`` During install step include the third party dependencies. This option is used for preparing Cutter binary release packges.
|
||||
|
||||
@ -253,28 +272,6 @@ Or if one wants to explicitly disable an option:
|
||||
cmake -B build -DCUTTER_ENABLE_PYTHON=OFF
|
||||
|
||||
|
||||
--------------
|
||||
|
||||
Compiling Cutter with Breakpad Support
|
||||
--------------------------------------
|
||||
|
||||
If you want to build Cutter with crash handling system, you will want to first prepare Breakpad.
|
||||
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"
|
||||
|
||||
|
||||
--------------
|
||||
|
||||
Troubleshooting
|
||||
|
@ -24,9 +24,9 @@ copyright = '2020, The Cutter Developers'
|
||||
author = 'The Cutter Developers'
|
||||
|
||||
# The short X.Y version
|
||||
version = '2.0'
|
||||
version = '2.2'
|
||||
# The full version, including a2lpha/beta/rc tags
|
||||
release = '2.0.2'
|
||||
release = '2.2.0'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
@ -1,32 +0,0 @@
|
||||
Crash Handling System
|
||||
=====================
|
||||
|
||||
Cutter uses `Breakpad <https://github.com/google/breakpad>`__ as a backend
|
||||
for crash handling.
|
||||
|
||||
Crash Handling System is disabled by default to not interfere with developers while debugging.
|
||||
To enable this system, set the ``CUTTER_ENABLE_CRASH_REPORTS`` build option.
|
||||
|
||||
Solution Description
|
||||
--------------------
|
||||
|
||||
There are only 2 source files:
|
||||
|
||||
* ``CrashHandler.h``
|
||||
* ``CrashHandler.cpp``
|
||||
|
||||
And the API is very simple: One function, ``initCrashHandler()``, enables the Crash Handling System if
|
||||
``CUTTER_ENABLE_CRASH_REPORTS`` is true, otherwise it does nothing.
|
||||
|
||||
As soon as a signal is raised, ``crashHandler(int signum)`` is called with the signal's code as an argument.
|
||||
This function first writes a crash dump to the operating system's temporary directory to catch core and
|
||||
memory state as it was at the moment of the crash.
|
||||
|
||||
Then the crash dialog is shown:
|
||||
|
||||
.. image :: /images/crash-dialog.png
|
||||
|
||||
If the user chooses to create a crash dump, the prepared dump is moved to the directory specified by the user.
|
||||
And then the success dialog is shown:
|
||||
|
||||
.. image :: /images/success-dump-dialog.png
|
@ -47,7 +47,7 @@ Example:
|
||||
|
||||
.. code:: cpp
|
||||
|
||||
QJsonArray array = Core()->cmdj("pdj 1 @ main").array();
|
||||
CutterJson array = Core()->cmdj("pdj 1 @ main");
|
||||
|
||||
Seek the Current File
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
@ -257,7 +257,7 @@ In order to update one submodule individually, use the following code:
|
||||
.. code:: sh
|
||||
|
||||
cd rizin
|
||||
git checkout master && git pull
|
||||
git checkout dev && git pull
|
||||
cd ..
|
||||
git add rizin
|
||||
git commit -m "Update rizin submodule"
|
||||
|
@ -4,7 +4,7 @@ Release Procedure
|
||||
1. Update translations submodule `<https://github.com/rizinorg/cutter-translations>`_
|
||||
1. The latest archive from Crowdin should already be in the repository, if not make sure to merge any automated Pull Request from Crowdin (e.g. https://github.com/rizinorg/cutter-translations/pull/9)
|
||||
2. Update submodule in cutter
|
||||
2. If there is a desire to keep working in the master branch, create branch for the release and do all the following work there.
|
||||
2. Merge the current state of dev into stable. This can happen even earlier in order to feature-freeze the release while keeping development on dev alive. The rizin submodule on stable should point to a commit of stable in rizin and dev to a commit in dev.
|
||||
3. Lock rzghidra and rzdec versions downloaded by packaging scripts. Specify a tag or commit hash.
|
||||
4. Update version
|
||||
#. appveyor.yml
|
||||
@ -19,11 +19,11 @@ Release Procedure
|
||||
6. Create a GitHub release, mark it as pre-release save draft, set the tag to v1.11.0-rc1
|
||||
7. Wait for packages to build
|
||||
8. On all operating systems do the `Basic testing procedure`_ to ensure nothing badly broken.
|
||||
9. If any major problems are found, open an issue and fix them. If a release branch is used fix them in master and cherry pick into release branch. If the amount of changes is sufficiently large repeat from step 3. increasing rc number by one.
|
||||
9. If any major problems are found, open an issue and fix them in dev and cherry pick into release branch. If the amount of changes is sufficiently large repeat from step 3. increasing rc number by one.
|
||||
10. Update version to 1.11.0
|
||||
11. Create tag
|
||||
12. Create release
|
||||
* Fill the release notes in the Release description. Preparing release notes can begin earlier. Compare current master or release branch against previous release to find all the changes. Choose the most important ones. Don't duplicate the commit log. Release notes should be a summary for people who don't want to read whole commit log. Group related changes together under titles such as "New features", "Bug Fixes", "Decompiler", "Rizin" and similar.
|
||||
* Fill the release notes in the Release description. Preparing release notes can begin earlier. Compare current dev branch against previous release to find all the changes. Choose the most important ones. Don't duplicate the commit log. Release notes should be a summary for people who don't want to read whole commit log. Group related changes together under titles such as "New features", "Bug Fixes", "Decompiler", "Rizin" and similar.
|
||||
13. Prepare announcement tweets and messages to send in the Telegram group, reddit, and others.
|
||||
14. Close milestone if there was one
|
||||
|
||||
@ -33,8 +33,7 @@ Bugfix Release
|
||||
--------------
|
||||
The process for bugfix release is similar no normal release procedure described above with some differences.
|
||||
|
||||
* Create the branch from the last tag instead of master or reuse the branch from x.y.0 release if it was already created.
|
||||
* Cherry pick required bugfixes from master into the branch.
|
||||
* Cherry pick required bugfixes from dev into the stable.
|
||||
* Increase the third version number x.y.n into x.y.(n+1) .
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@ How can you help?
|
||||
|
||||
The following sections suggest ways you can contribute to Cutter's documentation. The list isn't complete as the possibilities are limitless.
|
||||
|
||||
The source for this documentation is available in the `docs directory <https://github.com/rizinorg/cutter/tree/master/docs>`_ on Cutter's repository. This source can be generated according to the steps described in the :ref:`building docs page<contributing/docs/building-docs:Building docs>`. When the docs are updated, they are generated and pushed directly to the website at <https://cutter.re/docs>. The source for the website and blog are available on the `cutter.re's repository <https://github.com/rizinorg/cutter.re>`_ and are served from the ``gh-pages`` branch.
|
||||
The source for this documentation is available in the `docs directory <https://github.com/rizinorg/cutter/tree/dev/docs>`_ on Cutter's repository. This source can be generated according to the steps described in the :ref:`building docs page<contributing/docs/building-docs:Building docs>`. When the docs are updated, they are generated and pushed directly to the website at <https://cutter.re/docs>. The source for the website and blog are available on the `cutter.re's repository <https://github.com/rizinorg/cutter.re>`_ and are served from the ``gh-pages`` branch.
|
||||
|
||||
.. tip::
|
||||
Document what you wished to see. If you are a user of Cutter, try to think what things you would want to see documented when you started using the project. Sometimes, the best contributions are coming from your own needs.
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 29 KiB |
Binary file not shown.
Before Width: | Height: | Size: 14 KiB |
@ -40,21 +40,45 @@ Options
|
||||
**2**
|
||||
aaaa (experimental)
|
||||
|
||||
.. option:: -a, --arch <arch>
|
||||
|
||||
Sets a specific architecture name.
|
||||
|
||||
.. option:: -b, --bits <bits>
|
||||
|
||||
Sets a specific architecture bits.
|
||||
|
||||
.. option:: -c, --cpu <cpu>
|
||||
|
||||
Sets a specific CPU.
|
||||
|
||||
.. option:: -o, --os <os>
|
||||
|
||||
Sets a specific operating system.
|
||||
|
||||
.. option:: -e, --endian <big|little>
|
||||
|
||||
Sets the endianness (big or little).
|
||||
|
||||
.. option:: -F, --format <name>
|
||||
|
||||
Force using a specific file format (bin plugin)
|
||||
Force using a specific file format (bin plugin).
|
||||
|
||||
.. option:: -B, --base <base address>
|
||||
|
||||
Load binary at a specific base address
|
||||
Load binary at a specific base address.
|
||||
|
||||
.. option:: -m, --map <map address>
|
||||
|
||||
Map the binary at a specific address.
|
||||
|
||||
.. option:: -i <file>
|
||||
|
||||
Run script file
|
||||
Run script file.
|
||||
|
||||
.. option:: -p, --project <file>
|
||||
|
||||
Load project file
|
||||
Load project file.
|
||||
|
||||
.. option:: -w, --writemode
|
||||
|
||||
@ -62,9 +86,13 @@ Options
|
||||
When used together with -A/--analysis <level>, it will open a file directly
|
||||
in write mode without any further dialog or confirmation.
|
||||
|
||||
.. option:: -P, --phymode
|
||||
|
||||
Disables virtual addressing.
|
||||
|
||||
.. option:: --pythonhome <PYTHONHOME>
|
||||
|
||||
PYTHONHOME to use for the embedded python interpreter
|
||||
PYTHONHOME to use for the embedded python interpreter.
|
||||
|
||||
.. option:: --no-output-redirect
|
||||
|
||||
|
@ -103,15 +103,6 @@ Set Structure Offset
|
||||
|
||||
**Steps:** -> Structure offset
|
||||
|
||||
Link a Type to Address
|
||||
----------------------------------------
|
||||
**Description:** You can link type, enum or structure to a specific address. Types, structures and enums can be defined in the Types widget.
|
||||
|
||||
**Steps:** Right-click on an instruction and choose ``Link Type to Address``.
|
||||
|
||||
**Shortcut:** :kbd:`L`
|
||||
|
||||
|
||||
Show Cross References
|
||||
----------------------------------------
|
||||
**Description:** Show X-Refs from and to the specific location. This option will open Cutter's X-Refs dialog in which you will be able to see a list of X-Refs from and to the selected location, in addition to a preview of each cross-reference to quickly inspect the different usages.
|
||||
|
@ -89,8 +89,8 @@ Show VTables
|
||||
|
||||
**Steps:** Windows -> Info... -> VTables
|
||||
|
||||
Show Zignatures
|
||||
Show Signatures
|
||||
----------------------------------------
|
||||
**Description:** Cutter has its own format of signatures, called Zignatures. This widget lists all the loaded Zignatures.
|
||||
**Description:** Cutter supports the creation and the utilization of signatures. This widget lists all the signatures available to cutter.
|
||||
|
||||
**Steps:** Windows -> Info... -> Zignatures
|
||||
**Steps:** Windows -> Info... -> Signatures
|
@ -62,8 +62,6 @@ Disassembly View Shortcuts
|
||||
+-------------+----------------------------------+
|
||||
| Y | Edit/rename local variables |
|
||||
+-------------+----------------------------------+
|
||||
| L | Link a type/struct to address |
|
||||
+-------------+----------------------------------+
|
||||
| A | Set current address to String |
|
||||
+-------------+----------------------------------+
|
||||
| C | Set current address to Code |
|
||||
|
2
rizin
2
rizin
@ -1 +1 @@
|
||||
Subproject commit 381f22d7cc81bf2eb6663a690a715ff4f8f09373
|
||||
Subproject commit 6bfc67a2868e07ab89ff931b96dfd3bc65e7371e
|
@ -3,4 +3,6 @@ brew "ccache"
|
||||
brew "openssl"
|
||||
brew "xz"
|
||||
brew "llvm"
|
||||
brew "meson"
|
||||
brew "meson"
|
||||
brew "coreutils"
|
||||
brew "pkg-config"
|
||||
|
@ -1,34 +0,0 @@
|
||||
{
|
||||
'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',
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
import re
|
||||
import atexit
|
||||
|
||||
if len(sys.argv) != 3:
|
||||
print(f"usage: {sys.argv[0]} [Cutter.AppImage] [symbols dir]")
|
||||
exit(1)
|
||||
|
||||
root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
|
||||
def store_syms(syms, syms_dir):
|
||||
m = re.match(b"MODULE ([^ ]+) ([^ ]+) ([^ ]+) (.+)\n.*", syms)
|
||||
if m is None:
|
||||
print("Invalid dump_syms output")
|
||||
return
|
||||
|
||||
(modos, modarch, modhash, modname) = m.groups()
|
||||
modname = modname.decode("utf-8")
|
||||
modhash = modhash.decode("utf-8")
|
||||
symdir = os.path.join(syms_dir, modname, modhash)
|
||||
symfile = f"{modname}.sym"
|
||||
os.makedirs(symdir)
|
||||
symfile_path = os.path.join(symdir, symfile)
|
||||
with open(symfile_path, "wb") as f:
|
||||
f.write(syms)
|
||||
|
||||
print(symfile_path)
|
||||
|
||||
def dump_syms(binary, syms_dir):
|
||||
dump_syms_exec = os.path.join(root, "breakpad/src/tools/linux/dump_syms/dump_syms")
|
||||
syms = subprocess.run([dump_syms_exec, binary], capture_output=True).stdout
|
||||
store_syms(syms, syms_dir)
|
||||
|
||||
appimage = sys.argv[1]
|
||||
syms_dst = sys.argv[2]
|
||||
|
||||
# stdbuf workaround is needed before https://github.com/AppImage/AppImageKit/commit/e827baa719f5444aeef7202fe1f71c97d4200dde
|
||||
appimage_p = subprocess.Popen(["stdbuf", "-oL", appimage, "--appimage-mount"], stdout=subprocess.PIPE)
|
||||
def kill_appimage():
|
||||
appimage_p.kill()
|
||||
atexit.register(kill_appimage)
|
||||
mount_dir = appimage_p.stdout.readline().strip().decode("utf-8")
|
||||
|
||||
binaries = [ os.path.join(mount_dir, "usr/bin/cutter") ]
|
||||
for f in os.scandir(os.path.join(mount_dir, "usr/lib")):
|
||||
if f.is_dir() or f.is_symlink():
|
||||
continue
|
||||
binaries.append(f.path)
|
||||
|
||||
for b in binaries:
|
||||
dump_syms(b, syms_dst)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,54 +1,55 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
cd $(dirname "${BASH_SOURCE[0]}")/..
|
||||
mkdir -p cutter-deps && cd cutter-deps
|
||||
|
||||
LINUX_FILE="cutter-deps-linux.tar.gz"
|
||||
LINUX_MD5=eb2710548d951823e6b5340c33c8fc99
|
||||
LINUX_URL=https://github.com/rizinorg/cutter-deps/releases/download/v14/cutter-deps-linux.tar.gz
|
||||
DEPS_FILE_linux_x86_64=cutter-deps-linux-x86_64.tar.gz
|
||||
DEPS_SHA256_linux_x86_64=0721c85548bbcf31f6911cdb2227e5efb4a20c34262672d4cd2193db166b2f8c
|
||||
|
||||
MACOS_FILE="cutter-deps-macos.tar.gz"
|
||||
MACOS_MD5=f921c007430eec38b06acef8cc0fe42a
|
||||
MACOS_URL=https://github.com/rizinorg/cutter-deps/releases/download/v14/cutter-deps-macos.tar.gz
|
||||
DEPS_FILE_macos_x86_64=cutter-deps-macos-x86_64.tar.gz
|
||||
DEPS_SHA256_macos_x86_64=0a23fdec3012a8af76675d6f3ff39cf9df9b08c13d1156fb7ffcc0e495c9407f
|
||||
|
||||
WIN_FILE="cutter-deps-win.tar.gz"
|
||||
WIN_MD5=09aa544e62cdd786df3598f1ff340f9e
|
||||
WIN_URL=https://github.com/rizinorg/cutter-deps/releases/download/v14/cutter-deps-win.tar.gz
|
||||
DEPS_FILE_macos_arm64=cutter-deps-macos-arm64.tar.gz
|
||||
DEPS_SHA256_macos_arm64=f9b9a5569bd23c9b5e45836b82aba7576a5c53df4871380a55c370b9d7f88615
|
||||
|
||||
DEPS_FILE_win_x86_64=cutter-deps-win-x86_64.tar.gz
|
||||
DEPS_SHA256_win_x86_64=9ab4e89732a3df0859a26fd5de6d9f3cb80106cbe2539340af831ed298625076
|
||||
|
||||
DEPS_BASE_URL=https://github.com/rizinorg/cutter-deps/releases/download/v15
|
||||
|
||||
ARCH=x86_64
|
||||
if [ "$OS" == "Windows_NT" ]; then
|
||||
FILE="${WIN_FILE}"
|
||||
MD5="${WIN_MD5}"
|
||||
URL="${WIN_URL}"
|
||||
PLATFORM=win
|
||||
else
|
||||
UNAME_S="$(uname -s)"
|
||||
if [ "$UNAME_S" == "Linux" ]; then
|
||||
FILE="${LINUX_FILE}"
|
||||
MD5="${LINUX_MD5}"
|
||||
URL="${LINUX_URL}"
|
||||
PLATFORM=linux
|
||||
elif [ "$UNAME_S" == "Darwin" ]; then
|
||||
FILE="${MACOS_FILE}"
|
||||
MD5="${MACOS_MD5}"
|
||||
URL="${MACOS_URL}"
|
||||
PLATFORM=macos
|
||||
ARCH=$(uname -m)
|
||||
else
|
||||
echo "Unsupported Platform: uname -s => $UNAME_S, \$OS => $OS"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
curl -L "$URL" -o "$FILE" || exit 1
|
||||
DEPS_FILE=DEPS_FILE_${PLATFORM}_${ARCH}
|
||||
DEPS_FILE=${!DEPS_FILE}
|
||||
DEPS_SHA256=DEPS_SHA256_${PLATFORM}_${ARCH}
|
||||
DEPS_SHA256=${!DEPS_SHA256}
|
||||
DEPS_URL=${DEPS_BASE_URL}/${DEPS_FILE}
|
||||
|
||||
if [ "$UNAME_S" == "Darwin" ]; then
|
||||
if [ "$(md5 -r "$FILE")" != "$MD5 $FILE" ]; then \
|
||||
echo "MD5 mismatch for file $FILE"; \
|
||||
exit 1; \
|
||||
else \
|
||||
echo "$FILE OK"; \
|
||||
fi
|
||||
else
|
||||
echo "$MD5 $FILE" | md5sum -c - || exit 1
|
||||
SHA256SUM=sha256sum
|
||||
if ! command -v ${SHA256SUM} &> /dev/null; then
|
||||
SHA256SUM="shasum -a 256"
|
||||
fi
|
||||
|
||||
tar -xf "$FILE" || exit 1
|
||||
curl -L "$DEPS_URL" -o "$DEPS_FILE" || exit 1
|
||||
echo "$DEPS_SHA256 $DEPS_FILE" | ${SHA256SUM} -c - || exit 1
|
||||
|
||||
tar -xf "$DEPS_FILE" || exit 1
|
||||
|
||||
if [ -f relocate.sh ]; then
|
||||
./relocate.sh || exit 1
|
||||
|
@ -7,13 +7,13 @@ SCRIPTPATH=$(realpath "$(dirname "${BASH_SOURCE[0]}")")
|
||||
cd "$SCRIPTPATH/.."
|
||||
|
||||
if [[ ! -d jsdec ]]; then
|
||||
git clone https://github.com/rizinorg/jsdec.git --depth 1 --branch v0.2.x
|
||||
git clone https://github.com/rizinorg/jsdec.git --depth 2 --branch master
|
||||
fi
|
||||
|
||||
cd jsdec
|
||||
rm -rf build
|
||||
mkdir build && cd build
|
||||
meson --buildtype=release --libdir=share/rizin/plugins --datadir=share/rizin/plugins "$@" ../p
|
||||
meson --buildtype=release -Djsc_folder="../" "$@" ../p
|
||||
ninja
|
||||
ninja install
|
||||
|
||||
|
@ -1,33 +0,0 @@
|
||||
@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
|
||||
powershell -Command "git reset --hard 756daa536ad819eff80172aaab262fb71d1e89fd"
|
||||
|
||||
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
|
||||
SET GYP_MSVS_VERSION=2017
|
||||
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"
|
||||
devenv client\windows\breakpad_client.sln /upgrade
|
||||
|
||||
set PATH=%BUFF_PATH%
|
||||
msbuild /m %CD%\client\windows\breakpad_client.sln /p:Configuration=release /p:Platform=%ARCH% || exit /b 1
|
||||
CD %ROOT_DIR%
|
@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
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 --disable-tools --prefix=`pwd`/prefix && make -j4 && make install || exit 1
|
||||
|
||||
export CUSTOM_BREAKPAD_PREFIX="`pwd`/prefix"
|
||||
cd ..
|
@ -1,24 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPTPATH=$(realpath "$(dirname "${BASH_SOURCE[0]}")")
|
||||
|
||||
DIR="$SCRIPTPATH/.."
|
||||
cd "$DIR"
|
||||
BREAKPAD_FRAMEWORK_DIR="$DIR/breakpad/framework"
|
||||
BREAKPAD_DUMP_SYMS_DIR="$DIR/breakpad/bin"
|
||||
git clone https://github.com/google/breakpad.git
|
||||
mkdir $BREAKPAD_FRAMEWORK_DIR
|
||||
mkdir $BREAKPAD_DUMP_SYMS_DIR
|
||||
cd breakpad
|
||||
git checkout 4d550cceca107f36c4bc1ea1126b7d32cc50f424
|
||||
git apply "$SCRIPTPATH/breakpad_macos.patch"
|
||||
cd src/client/mac/ && xcodebuild -sdk macosx MACOSX_DEPLOYMENT_TARGET=10.14
|
||||
cp -R build/Release/Breakpad.framework "$BREAKPAD_FRAMEWORK_DIR"
|
||||
|
||||
cd $DIR/breakpad
|
||||
cp -R src/. framework/Breakpad.framework/Headers
|
||||
|
||||
export BREAKPAD_FRAMEWORK_DIR=$BREAKPAD_FRAMEWORK_DIR
|
||||
cd $DIR
|
19
scripts/rz-libswift.sh
Executable file
19
scripts/rz-libswift.sh
Executable file
@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
SCRIPTPATH=$(realpath "$(dirname "${BASH_SOURCE[0]}")")
|
||||
|
||||
cd "$SCRIPTPATH/.."
|
||||
|
||||
if [[ ! -d libswift ]]; then
|
||||
git clone https://github.com/rizinorg/rz-libswift.git --depth 1 libswift
|
||||
fi
|
||||
|
||||
cd libswift
|
||||
rm -rf build || sleep 0
|
||||
mkdir build && cd build
|
||||
meson --buildtype=release "$@" ..
|
||||
ninja
|
||||
ninja install
|
||||
|
25
scripts/rz-libyara.sh
Executable file
25
scripts/rz-libyara.sh
Executable file
@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPTPATH=$(realpath "$(dirname "${BASH_SOURCE[0]}")")
|
||||
INSTALL_PREFIX="$1"
|
||||
EXTRA_CMAKE_OPTS="$2"
|
||||
|
||||
cd "$SCRIPTPATH/.."
|
||||
|
||||
if [[ ! -d rz_libyara ]]; then
|
||||
git clone https://github.com/rizinorg/rz-libyara.git --depth 1 rz_libyara
|
||||
git -C rz_libyara submodule init
|
||||
git -C rz_libyara submodule update
|
||||
fi
|
||||
|
||||
cd rz_libyara
|
||||
|
||||
meson --buildtype=release --pkg-config-path="$INSTALL_PREFIX/lib/pkgconfig" --prefix="$INSTALL_PREFIX" -Duse_sys_yara=disabled build
|
||||
ninja -C build install
|
||||
|
||||
cd cutter-plugin
|
||||
mkdir build && cd build
|
||||
cmake -G Ninja -DRIZIN_INSTALL_PLUGDIR="../build" -DCMAKE_INSTALL_PREFIX="$INSTALL_PREFIX" $EXTRA_CMAKE_OPTS ..
|
||||
ninja
|
||||
ninja install
|
17
scripts/rz-silhouette.sh
Executable file
17
scripts/rz-silhouette.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
SCRIPTPATH=$(realpath "$(dirname "${BASH_SOURCE[0]}")")
|
||||
INSTALL_PREFIX="$1"
|
||||
EXTRA_CMAKE_OPTS="$2"
|
||||
|
||||
cd "$SCRIPTPATH/.."
|
||||
|
||||
if [[ ! -d rz-silhouette ]]; then
|
||||
git clone https://github.com/rizinorg/rz-silhouette.git --depth 1 rz-silhouette
|
||||
fi
|
||||
|
||||
cd rz-silhouette
|
||||
|
||||
meson --buildtype=release --pkg-config-path="$INSTALL_PREFIX/lib/pkgconfig" --prefix="$INSTALL_PREFIX" build
|
||||
ninja -C build install
|
32
scripts/tarball.sh
Executable file
32
scripts/tarball.sh
Executable file
@ -0,0 +1,32 @@
|
||||
#!/bin/bash
|
||||
|
||||
NAME=${1:-Cutter}
|
||||
|
||||
set -xe
|
||||
cd $(dirname "${BASH_SOURCE[0]}")/..
|
||||
|
||||
shopt -s extglob
|
||||
shopt -s dotglob
|
||||
mkdir "${NAME}"
|
||||
cp -r !(${NAME}) "${NAME}"
|
||||
|
||||
pushd "${NAME}"
|
||||
git clean -dxff .
|
||||
git submodule update --init --recursive
|
||||
|
||||
pushd rizin
|
||||
git clean -dxff .
|
||||
# Possible option: pre-download all subproject, however this makes the tarball huge.
|
||||
# As opposed to meson dist used for rizin tarballs, this will not just download the ones
|
||||
# used in a default build, but all of them, including multiple capstone variants.
|
||||
# meson subprojects download
|
||||
popd
|
||||
|
||||
pushd src/translations
|
||||
git clean -dxff .
|
||||
popd
|
||||
|
||||
find . -name ".git*" | xargs rm -rfv
|
||||
popd
|
||||
|
||||
tar -czvf "${NAME}-src.tar.gz" "${NAME}"
|
@ -4,10 +4,14 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CutterConfig.h.in"
|
||||
set(SOURCES
|
||||
Main.cpp
|
||||
core/Cutter.cpp
|
||||
core/CutterJson.cpp
|
||||
core/RizinCpp.cpp
|
||||
core/Basefind.cpp
|
||||
dialogs/EditStringDialog.cpp
|
||||
dialogs/WriteCommandsDialogs.cpp
|
||||
widgets/DisassemblerGraphView.cpp
|
||||
widgets/OverviewView.cpp
|
||||
common/DisassemblyPreview.cpp
|
||||
common/RichTextPainter.cpp
|
||||
dialogs/InitialOptionsDialog.cpp
|
||||
dialogs/AboutDialog.cpp
|
||||
@ -24,7 +28,7 @@ set(SOURCES
|
||||
common/DirectionalComboBox.cpp
|
||||
dialogs/preferences/AsmOptionsWidget.cpp
|
||||
dialogs/NewFileDialog.cpp
|
||||
common/AnalTask.cpp
|
||||
common/AnalysisTask.cpp
|
||||
widgets/CommentsWidget.cpp
|
||||
widgets/ConsoleWidget.cpp
|
||||
widgets/Dashboard.cpp
|
||||
@ -41,6 +45,7 @@ set(SOURCES
|
||||
widgets/SymbolsWidget.cpp
|
||||
menus/DisassemblyContextMenu.cpp
|
||||
menus/DecompilerContextMenu.cpp
|
||||
menus/FlirtContextMenu.cpp
|
||||
widgets/DisassemblyWidget.cpp
|
||||
widgets/HexdumpWidget.cpp
|
||||
common/Configuration.cpp
|
||||
@ -69,10 +74,9 @@ set(SOURCES
|
||||
widgets/CutterTreeWidget.cpp
|
||||
widgets/GraphWidget.cpp
|
||||
widgets/OverviewWidget.cpp
|
||||
common/JsonTreeItem.cpp
|
||||
common/JsonModel.cpp
|
||||
dialogs/VersionInfoDialog.cpp
|
||||
widgets/ZignaturesWidget.cpp
|
||||
widgets/FlirtWidget.cpp
|
||||
common/AsyncTask.cpp
|
||||
dialogs/AsyncTaskDialog.cpp
|
||||
widgets/StackWidget.cpp
|
||||
@ -109,7 +113,6 @@ set(SOURCES
|
||||
plugins/PluginManager.cpp
|
||||
common/BasicBlockHighlighter.cpp
|
||||
common/BasicInstructionHighlighter.cpp
|
||||
dialogs/LinkTypeDialog.cpp
|
||||
widgets/ColorPicker.cpp
|
||||
common/ColorThemeWorker.cpp
|
||||
widgets/ColorThemeComboBox.cpp
|
||||
@ -139,18 +142,25 @@ set(SOURCES
|
||||
widgets/RizinGraphWidget.cpp
|
||||
widgets/CallGraph.cpp
|
||||
widgets/AddressableDockWidget.cpp
|
||||
dialogs/preferences/AnalOptionsWidget.cpp
|
||||
dialogs/preferences/AnalysisOptionsWidget.cpp
|
||||
common/DecompilerHighlighter.cpp
|
||||
dialogs/GlibcHeapInfoDialog.cpp
|
||||
widgets/HeapDockWidget.cpp
|
||||
widgets/GlibcHeapWidget.cpp
|
||||
dialogs/GlibcHeapBinsDialog.cpp
|
||||
widgets/HeapBinsGraphView.cpp
|
||||
dialogs/ArenaInfoDialog.cpp
|
||||
tools/basefind/BaseFindDialog.cpp
|
||||
tools/basefind/BaseFindSearchDialog.cpp
|
||||
tools/basefind/BaseFindResultsDialog.cpp
|
||||
)
|
||||
set(HEADER_FILES
|
||||
core/Cutter.h
|
||||
core/CutterCommon.h
|
||||
core/CutterDescriptions.h
|
||||
core/CutterJson.h
|
||||
core/RizinCpp.h
|
||||
core/Basefind.h
|
||||
dialogs/EditStringDialog.h
|
||||
dialogs/WriteCommandsDialogs.h
|
||||
widgets/DisassemblerGraphView.h
|
||||
@ -172,7 +182,7 @@ set(HEADER_FILES
|
||||
common/DirectionalComboBox.h
|
||||
dialogs/InitialOptionsDialog.h
|
||||
dialogs/NewFileDialog.h
|
||||
common/AnalTask.h
|
||||
common/AnalysisTask.h
|
||||
widgets/CommentsWidget.h
|
||||
widgets/ConsoleWidget.h
|
||||
widgets/Dashboard.h
|
||||
@ -189,6 +199,7 @@ set(HEADER_FILES
|
||||
widgets/SymbolsWidget.h
|
||||
menus/DisassemblyContextMenu.h
|
||||
menus/DecompilerContextMenu.h
|
||||
menus/FlirtContextMenu.h
|
||||
widgets/DisassemblyWidget.h
|
||||
widgets/HexdumpWidget.h
|
||||
common/Configuration.h
|
||||
@ -217,10 +228,9 @@ set(HEADER_FILES
|
||||
widgets/CutterTreeWidget.h
|
||||
widgets/GraphWidget.h
|
||||
widgets/OverviewWidget.h
|
||||
common/JsonTreeItem.h
|
||||
common/JsonModel.h
|
||||
dialogs/VersionInfoDialog.h
|
||||
widgets/ZignaturesWidget.h
|
||||
widgets/FlirtWidget.h
|
||||
common/AsyncTask.h
|
||||
dialogs/AsyncTaskDialog.h
|
||||
widgets/StackWidget.h
|
||||
@ -257,7 +267,6 @@ set(HEADER_FILES
|
||||
common/RunScriptTask.h
|
||||
common/Json.h
|
||||
dialogs/EditMethodDialog.h
|
||||
common/CrashHandler.h
|
||||
dialogs/TypesInteractionDialog.h
|
||||
widgets/SdbWidget.h
|
||||
plugins/PluginManager.h
|
||||
@ -270,7 +279,6 @@ set(HEADER_FILES
|
||||
widgets/MemoryDockWidget.h
|
||||
widgets/ColorThemeListView.h
|
||||
dialogs/preferences/ColorThemeEditDialog.h
|
||||
dialogs/LinkTypeDialog.h
|
||||
common/BugReporting.h
|
||||
common/HighDpiPixmap.h
|
||||
widgets/GraphLayout.h
|
||||
@ -297,13 +305,17 @@ set(HEADER_FILES
|
||||
widgets/RizinGraphWidget.h
|
||||
widgets/CallGraph.h
|
||||
widgets/AddressableDockWidget.h
|
||||
dialogs/preferences/AnalOptionsWidget.h
|
||||
dialogs/preferences/AnalysisOptionsWidget.h
|
||||
common/DecompilerHighlighter.h
|
||||
dialogs/GlibcHeapInfoDialog.h
|
||||
widgets/HeapDockWidget.h
|
||||
widgets/GlibcHeapWidget.h
|
||||
dialogs/GlibcHeapBinsDialog.h
|
||||
widgets/HeapBinsGraphView.h
|
||||
dialogs/ArenaInfoDialog.h
|
||||
tools/basefind/BaseFindDialog.h
|
||||
tools/basefind/BaseFindSearchDialog.h
|
||||
tools/basefind/BaseFindResultsDialog.h
|
||||
)
|
||||
set(UI_FILES
|
||||
dialogs/AboutDialog.ui
|
||||
@ -334,13 +346,12 @@ set(UI_FILES
|
||||
dialogs/preferences/InitializationFileEditor.ui
|
||||
widgets/QuickFilterView.ui
|
||||
widgets/DecompilerWidget.ui
|
||||
widgets/ClassesWidget.ui
|
||||
widgets/VTablesWidget.ui
|
||||
widgets/TypesWidget.ui
|
||||
widgets/SearchWidget.ui
|
||||
dialogs/RizinPluginsDialog.ui
|
||||
dialogs/VersionInfoDialog.ui
|
||||
widgets/ZignaturesWidget.ui
|
||||
widgets/FlirtWidget.ui
|
||||
dialogs/AsyncTaskDialog.ui
|
||||
dialogs/RizinTaskDialog.ui
|
||||
widgets/StackWidget.ui
|
||||
@ -363,17 +374,20 @@ set(UI_FILES
|
||||
dialogs/EditMethodDialog.ui
|
||||
dialogs/TypesInteractionDialog.ui
|
||||
widgets/SdbWidget.ui
|
||||
dialogs/LinkTypeDialog.ui
|
||||
widgets/ColorPicker.ui
|
||||
dialogs/preferences/ColorThemeEditDialog.ui
|
||||
widgets/ListDockWidget.ui
|
||||
dialogs/LayoutManager.ui
|
||||
widgets/RizinGraphWidget.ui
|
||||
dialogs/preferences/AnalOptionsWidget.ui
|
||||
dialogs/preferences/AnalysisOptionsWidget.ui
|
||||
dialogs/GlibcHeapInfoDialog.ui
|
||||
widgets/HeapDockWidget.ui
|
||||
widgets/GlibcHeapWidget.ui
|
||||
dialogs/GlibcHeapBinsDialog.ui
|
||||
dialogs/ArenaInfoDialog.ui
|
||||
tools/basefind/BaseFindDialog.ui
|
||||
tools/basefind/BaseFindSearchDialog.ui
|
||||
tools/basefind/BaseFindResultsDialog.ui
|
||||
)
|
||||
set(QRC_FILES
|
||||
resources.qrc
|
||||
@ -383,20 +397,26 @@ set(QRC_FILES
|
||||
themes/lightstyle/light.qrc
|
||||
)
|
||||
|
||||
set(CUTTER_INCLUDE_DIRECTORIES core widgets common plugins menus .)
|
||||
|
||||
if (CUTTER_ENABLE_PYTHON)
|
||||
list(APPEND SOURCES common/QtResImporter.cpp common/PythonManager.cpp common/PythonAPI.cpp)
|
||||
list(APPEND HEADER_FILES common/QtResImporter.h common/PythonManager.h common/PythonAPI.h)
|
||||
endif()
|
||||
|
||||
if(CUTTER_ENABLE_CRASH_REPORTS)
|
||||
list(APPEND SOURCES common/CrashHandler.cpp)
|
||||
endif()
|
||||
|
||||
if(CUTTER_ENABLE_PYTHON_BINDINGS)
|
||||
if (CUTTER_QT6)
|
||||
set(PYSIDE_NAME PySide6)
|
||||
set(SHIBOKEN_COMMAND Shiboken6::shiboken6)
|
||||
else()
|
||||
set(PYSIDE_NAME PySide2)
|
||||
set(SHIBOKEN_COMMAND Shiboken2::shiboken2)
|
||||
endif()
|
||||
|
||||
set(BINDINGS_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bindings")
|
||||
set(BINDINGS_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}/bindings")
|
||||
|
||||
configure_file("${BINDINGS_SRC_DIR}/bindings.xml" "${BINDINGS_BUILD_DIR}/bindings.xml" COPYONLY) # trigger reconfigure if file changes
|
||||
configure_file("${BINDINGS_SRC_DIR}/bindings.xml.in" "${BINDINGS_BUILD_DIR}/bindings.xml")
|
||||
|
||||
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "${BINDINGS_SRC_DIR}/src_list.py" cmake "${BINDINGS_BUILD_DIR}" OUTPUT_VARIABLE BINDINGS_SOURCE)
|
||||
|
||||
@ -404,14 +424,40 @@ if(CUTTER_ENABLE_PYTHON_BINDINGS)
|
||||
|
||||
include_directories("${BINDINGS_BUILD_DIR}/CutterBindings")
|
||||
|
||||
set(SHIBOKEN_INCLUDE_DIRS "")
|
||||
if(APPLE AND _qt6Core_install_prefix)
|
||||
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt6Core_install_prefix}/include")
|
||||
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt6Core_install_prefix}/include/QtCore")
|
||||
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt6Core_install_prefix}/include/QtGui")
|
||||
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt6Core_install_prefix}/include/QtWidgets")
|
||||
endif()
|
||||
|
||||
if (CUTTER_QT6)
|
||||
list(APPEND SHIBOKEN_INCLUDE_DIRS ${Qt6Core_INCLUDE_DIRS} ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Gui_INCLUDE_DIRS})
|
||||
else()
|
||||
list(APPEND SHIBOKEN_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
foreach(_dir ${CUTTER_INCLUDE_DIRECTORIES})
|
||||
list(APPEND SHIBOKEN_INCLUDE_DIRS
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${_dir}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/cutter/${_dir}>
|
||||
)
|
||||
endforeach()
|
||||
list(APPEND SHIBOKEN_INCLUDE_DIRS ${Rizin_INCLUDE_DIRS})
|
||||
if (NOT WIN32)
|
||||
string(REPLACE ";" ":" SHIBOKEN_INCLUDE_DIRS "${SHIBOKEN_INCLUDE_DIRS}")
|
||||
endif()
|
||||
|
||||
set(SHIBOKEN_OPTIONS)
|
||||
list(APPEND SHIBOKEN_OPTIONS --include-paths="${SHIBOKEN_INCLUDE_DIRS}")
|
||||
if (WIN32)
|
||||
list(APPEND SHIBOKEN_OPTIONS --avoid-protected-hack)
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${BINDINGS_SOURCE}
|
||||
COMMAND Shiboken2::shiboken2 --project-file="${BINDINGS_BUILD_DIR}/bindings.txt" ${SHIBOKEN_OPTIONS} ${SHIBOKEN_EXTRA_OPTIONS}
|
||||
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/bindings/bindings.xml" "${BINDINGS_BUILD_DIR}/bindings.txt"
|
||||
COMMAND "${SHIBOKEN_COMMAND}" --project-file="${BINDINGS_BUILD_DIR}/bindings.txt" ${SHIBOKEN_OPTIONS} ${SHIBOKEN_EXTRA_OPTIONS}
|
||||
DEPENDS "${BINDINGS_BUILD_DIR}/bindings.xml" "${BINDINGS_BUILD_DIR}/bindings.txt"
|
||||
IMPLICIT_DEPENDS CXX "${CMAKE_CURRENT_SOURCE_DIR}/bindings/bindings.h"
|
||||
COMMENT "Generating Python bindings with shiboken2")
|
||||
else()
|
||||
@ -426,6 +472,7 @@ endif()
|
||||
|
||||
if (WIN32)
|
||||
set(PLATFORM_RESOURCES "img/cutter.rc")
|
||||
set(OPTIONS WIN32)
|
||||
else()
|
||||
set(PLATFORM_RESOURCES "")
|
||||
endif()
|
||||
@ -436,8 +483,11 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
|
||||
set_source_files_properties(${BINDINGS_SOURCE} PROPERTIES COMPILE_FLAGS -w)
|
||||
endif()
|
||||
|
||||
# Make a source group for Visual Studio
|
||||
set(CUTTER_SOURCES ${OPTIONS} ${UI_FILES} ${QRC_FILES} ${PLATFORM_RESOURCES} ${SOURCES} ${HEADER_FILES})
|
||||
source_group(TREE "${CMAKE_CURRENT_LIST_DIR}" FILES ${CUTTER_SOURCES})
|
||||
|
||||
add_executable(Cutter ${UI_FILES} ${QRC_FILES} ${PLATFORM_RESOURCES} ${SOURCES} ${HEADER_FILES} ${BINDINGS_SOURCE})
|
||||
add_executable(Cutter ${CUTTER_SOURCES} ${BINDINGS_SOURCE})
|
||||
set_target_properties(Cutter PROPERTIES
|
||||
OUTPUT_NAME cutter
|
||||
RUNTIME_OUTPUT_DIRECTORY ..
|
||||
@ -446,7 +496,9 @@ set_target_properties(Cutter PROPERTIES
|
||||
CXX_VISIBILITY_PRESET hidden)
|
||||
target_compile_definitions(Cutter PRIVATE CUTTER_SOURCE_BUILD)
|
||||
|
||||
set(CUTTER_INCLUDE_DIRECTORIES core widgets common plugins menus .)
|
||||
# Set Cutter as the startup project in Visual Studio
|
||||
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Cutter)
|
||||
|
||||
foreach(_dir ${CUTTER_INCLUDE_DIRECTORIES})
|
||||
target_include_directories(Cutter PUBLIC
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${_dir}>
|
||||
@ -459,19 +511,6 @@ if (TARGET Graphviz::GVC)
|
||||
target_compile_definitions(Cutter PRIVATE CUTTER_ENABLE_GRAPHVIZ)
|
||||
endif()
|
||||
|
||||
if(CUTTER_ENABLE_CRASH_REPORTS)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(Cutter PRIVATE Threads::Threads)
|
||||
|
||||
add_definitions(-DCUTTER_ENABLE_CRASH_REPORTS)
|
||||
if (NOT WIN32)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g ")
|
||||
endif()
|
||||
find_package(Breakpad REQUIRED)
|
||||
target_link_libraries(Cutter PRIVATE Breakpad::client)
|
||||
endif()
|
||||
|
||||
target_link_libraries(Cutter PUBLIC ${QT_PREFIX}::Core ${QT_PREFIX}::Widgets ${QT_PREFIX}::Gui PRIVATE ${QT_PREFIX}::Svg ${QT_PREFIX}::Network)
|
||||
if (CUTTER_QT6)
|
||||
target_link_libraries(Cutter PUBLIC Qt6::Core5Compat Qt6::SvgWidgets)
|
||||
@ -494,9 +533,17 @@ if(CUTTER_ENABLE_PYTHON)
|
||||
endif()
|
||||
target_link_libraries(Cutter PRIVATE ${PYTHON_LIBRARIES})
|
||||
if(CUTTER_ENABLE_PYTHON_BINDINGS)
|
||||
target_link_libraries(Cutter PRIVATE Shiboken2::libshiboken PySide2::pyside2)
|
||||
if (CUTTER_QT6)
|
||||
target_link_libraries(Cutter PRIVATE Shiboken6::libshiboken PySide6::pyside6)
|
||||
else()
|
||||
target_link_libraries(Cutter PRIVATE Shiboken2::libshiboken PySide2::pyside2)
|
||||
endif()
|
||||
|
||||
get_target_property(RAW_BINDINGS_INCLUDE_DIRS Cutter INCLUDE_DIRECTORIES)
|
||||
if(NOT CUTTER_USE_BUNDLED_RIZIN)
|
||||
get_target_property(RAW_RIZIN_INCLUDE_DIRS ${RIZIN_TARGET} INTERFACE_INCLUDE_DIRECTORIES)
|
||||
list(APPEND RAW_BINDINGS_INCLUDE_DIRS "${RAW_RIZIN_INCLUDE_DIRS}")
|
||||
endif()
|
||||
set(BINDINGS_INCLUDE_DIRS "")
|
||||
foreach(_dir ${RAW_BINDINGS_INCLUDE_DIRS})
|
||||
string(REGEX REPLACE "\\$<BUILD_INTERFACE:(.*)>" "\\1" _dir ${_dir})
|
||||
@ -512,7 +559,11 @@ if(CUTTER_ENABLE_PYTHON)
|
||||
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include/QtGui")
|
||||
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include/QtWidgets")
|
||||
endif()
|
||||
list(APPEND BINDINGS_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS})
|
||||
if (CUTTER_QT6)
|
||||
list(APPEND BINDINGS_INCLUDE_DIRS ${Qt6Core_INCLUDE_DIRS} ${Qt6Widgets_INCLUDE_DIRS} ${Qt6Gui_INCLUDE_DIRS})
|
||||
else()
|
||||
list(APPEND BINDINGS_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS})
|
||||
endif()
|
||||
list(APPEND BINDINGS_INCLUDE_DIRS ${Rizin_INCLUDE_DIRS})
|
||||
list(APPEND BINDINGS_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
if (NOT WIN32)
|
||||
@ -520,7 +571,7 @@ if(CUTTER_ENABLE_PYTHON)
|
||||
endif()
|
||||
|
||||
configure_file("${BINDINGS_SRC_DIR}/bindings.txt.in" "${BINDINGS_BUILD_DIR}/bindings.txt")
|
||||
add_compile_definitions(WIN32_LEAN_AND_MEAN)
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -552,17 +603,26 @@ install(TARGETS Cutter
|
||||
EXPORT CutterTargets
|
||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
|
||||
BUNDLE DESTINATION "." # needs to be tested
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT Devel
|
||||
)
|
||||
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT Devel)
|
||||
install(EXPORT CutterTargets
|
||||
NAMESPACE Cutter::
|
||||
DESTINATION "${ConfigPackageLocation}"
|
||||
DESTINATION "${CUTTER_INSTALL_CONFIGDIR}"
|
||||
COMPONENT Devel)
|
||||
include(CMakePackageConfigHelpers)
|
||||
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/CutterConfig.cmake.in
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/CutterConfig.cmake"
|
||||
INSTALL_DESTINATION "${CUTTER_INSTALL_CONFIGDIR}"
|
||||
NO_SET_AND_CHECK_MACRO
|
||||
NO_CHECK_REQUIRED_COMPONENTS_MACRO)
|
||||
write_basic_package_version_file(
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/CutterConfigVersion.cmake"
|
||||
VERSION "${CUTTER_VERSION_FULL}"
|
||||
COMPATIBILITY AnyNewerVersion)
|
||||
install(FILES
|
||||
../cmake/CutterConfig.cmake
|
||||
DESTINATION ${ConfigPackageLocation}
|
||||
COMPONENT Devel
|
||||
)
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/CutterConfig.cmake"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/CutterConfigVersion.cmake"
|
||||
DESTINATION ${CUTTER_INSTALL_CONFIGDIR}
|
||||
COMPONENT Devel)
|
||||
foreach(_file ${HEADER_FILES})
|
||||
# Can't use target PUBLIC_HEADER option for installing due to multiple directories
|
||||
get_filename_component(_header_dir "${_file}" DIRECTORY)
|
||||
@ -570,8 +630,8 @@ foreach(_file ${HEADER_FILES})
|
||||
endforeach()
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
install (FILES "img/cutter.svg"
|
||||
DESTINATION "share/icons/hicolor/scalable/apps/")
|
||||
install(FILES "img/cutter.svg"
|
||||
DESTINATION "share/icons/hicolor/scalable/apps/")
|
||||
install(FILES "re.rizin.cutter.desktop"
|
||||
DESTINATION "share/applications"
|
||||
COMPONENT Devel)
|
||||
|
@ -1,5 +1,4 @@
|
||||
#include "common/PythonManager.h"
|
||||
#include "common/CrashHandler.h"
|
||||
#include "CutterApplication.h"
|
||||
#include "plugins/PluginManager.h"
|
||||
#include "CutterConfig.h"
|
||||
@ -34,21 +33,24 @@
|
||||
// has RZ_GITTAP defined and uses it in rz_core_version().
|
||||
// After that, RZ_GITTAP is not defined anymore and RZ_VERSION is used.
|
||||
#ifdef RZ_GITTAP
|
||||
#define CUTTER_COMPILE_TIME_RZ_VERSION "" RZ_GITTAP
|
||||
# define CUTTER_COMPILE_TIME_RZ_VERSION "" RZ_GITTAP
|
||||
#else
|
||||
#define CUTTER_COMPILE_TIME_RZ_VERSION "" RZ_VERSION
|
||||
# define CUTTER_COMPILE_TIME_RZ_VERSION "" RZ_VERSION
|
||||
#endif
|
||||
|
||||
CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc, argv)
|
||||
{
|
||||
// Setup application information
|
||||
setApplicationVersion(CUTTER_VERSION_FULL);
|
||||
#ifdef Q_OS_MACOS
|
||||
setWindowIcon(QIcon(":/img/cutter_macos_simple.svg"));
|
||||
#else
|
||||
setWindowIcon(QIcon(":/img/cutter.svg"));
|
||||
#endif
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
setAttribute(Qt::AA_UseHighDpiPixmaps); // always enabled on Qt >= 6.0.0
|
||||
#endif
|
||||
setLayoutDirection(Qt::LeftToRight);
|
||||
|
||||
// WARN!!! Put initialization code below this line. Code above this line is mandatory to be run
|
||||
// First
|
||||
|
||||
@ -149,7 +151,7 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc
|
||||
}
|
||||
mainWindow->displayNewFileDialog();
|
||||
} else { // filename specified as positional argument
|
||||
bool askOptions = (clOptions.analLevel != AutomaticAnalysisLevel::Ask)
|
||||
bool askOptions = (clOptions.analysisLevel != AutomaticAnalysisLevel::Ask)
|
||||
|| !clOptions.fileOpenOptions.projectFile.isEmpty();
|
||||
mainWindow->openNewFile(clOptions.fileOpenOptions, askOptions);
|
||||
}
|
||||
@ -160,43 +162,29 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc
|
||||
appdir.cdUp(); // appdir
|
||||
|
||||
auto sleighHome = appdir;
|
||||
sleighHome.cd(
|
||||
"share/rizin/plugins/rz_ghidra_sleigh"); // appdir/share/rizin/plugins/rz_ghidra_sleigh
|
||||
// appdir/lib/rizin/plugins/rz_ghidra_sleigh/
|
||||
sleighHome.cd("lib/rizin/plugins/rz_ghidra_sleigh/");
|
||||
Core()->setConfig("ghidra.sleighhome", sleighHome.absolutePath());
|
||||
|
||||
auto jsdecHome = appdir;
|
||||
jsdecHome.cd("share/rizin/plugins/jsdec"); // appdir/share/rizin/plugins/jsdec
|
||||
qputenv("JSDEC_HOME", jsdecHome.absolutePath().toLocal8Bit());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
#if defined(Q_OS_MACOS) && defined(CUTTER_ENABLE_PACKAGING)
|
||||
{
|
||||
auto rzprefix = QDir(QCoreApplication::applicationDirPath()); // Contents/MacOS
|
||||
rzprefix.cdUp(); // Contents
|
||||
rzprefix.cd("Resources"); // Contents/Resources/rz
|
||||
rzprefix.cd("Resources"); // Contents/Resources/
|
||||
|
||||
auto sleighHome = rzprefix;
|
||||
sleighHome.cd(
|
||||
"share/rizin/plugins/rz_ghidra_sleigh"); // Contents/Resources/rz/share/rizin/plugins/rz_ghidra_sleigh
|
||||
// Contents/Resources/lib/rizin/plugins/rz_ghidra_sleigh
|
||||
sleighHome.cd("lib/rizin/plugins/rz_ghidra_sleigh");
|
||||
Core()->setConfig("ghidra.sleighhome", sleighHome.absolutePath());
|
||||
|
||||
# ifdef CUTTER_BUNDLE_JSDEC
|
||||
auto jsdecHome = rzprefix;
|
||||
jsdecHome.cd(
|
||||
"share/rizin/plugins/jsdec"); // Contents/Resources/rz/share/rizin/plugins/jsdec
|
||||
qputenv("JSDEC_HOME", jsdecHome.absolutePath().toLocal8Bit());
|
||||
# endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_WIN) && defined(CUTTER_ENABLE_PACKAGING)
|
||||
{
|
||||
# ifdef CUTTER_BUNDLE_JSDEC
|
||||
qputenv("JSDEC_HOME", "lib\\plugins\\jsdec");
|
||||
# endif
|
||||
auto sleighHome = QDir(QCoreApplication::applicationDirPath());
|
||||
sleighHome.cd("lib/plugins/rz_ghidra_sleigh");
|
||||
sleighHome.cd("lib/rizin/plugins/rz_ghidra_sleigh");
|
||||
Core()->setConfig("ghidra.sleighhome", sleighHome.absolutePath());
|
||||
}
|
||||
#endif
|
||||
@ -308,6 +296,89 @@ bool CutterApplication::loadTranslations()
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList CutterApplication::getArgs() const
|
||||
{
|
||||
auto &options = clOptions.fileOpenOptions;
|
||||
|
||||
QStringList args;
|
||||
switch (clOptions.analysisLevel) {
|
||||
case AutomaticAnalysisLevel::None:
|
||||
args.push_back("-A");
|
||||
args.push_back("0");
|
||||
break;
|
||||
case AutomaticAnalysisLevel::AAA:
|
||||
args.push_back("-A");
|
||||
args.push_back("1");
|
||||
break;
|
||||
case AutomaticAnalysisLevel::AAAA:
|
||||
args.push_back("-A");
|
||||
args.push_back("2");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!options.useVA) {
|
||||
args.push_back("-P");
|
||||
}
|
||||
if (options.writeEnabled) {
|
||||
args.push_back("-w");
|
||||
}
|
||||
if (!options.script.isEmpty()) {
|
||||
args.push_back("-i");
|
||||
args.push_back(options.script);
|
||||
}
|
||||
if (!options.projectFile.isEmpty()) {
|
||||
args.push_back("-p");
|
||||
args.push_back(options.projectFile);
|
||||
}
|
||||
if (!options.arch.isEmpty()) {
|
||||
args.push_back("-a");
|
||||
args.push_back(options.arch);
|
||||
}
|
||||
if (options.bits > 0) {
|
||||
args.push_back("-b");
|
||||
args.push_back(QString::asprintf("%d", options.bits));
|
||||
}
|
||||
if (!options.cpu.isEmpty()) {
|
||||
args.push_back("-c");
|
||||
args.push_back(options.cpu);
|
||||
}
|
||||
if (!options.os.isEmpty()) {
|
||||
args.push_back("-o");
|
||||
args.push_back(options.os);
|
||||
}
|
||||
|
||||
switch (options.endian) {
|
||||
case InitialOptions::Endianness::Little:
|
||||
args.push_back("-e");
|
||||
args.push_back("little");
|
||||
break;
|
||||
case InitialOptions::Endianness::Big:
|
||||
args.push_back("-e");
|
||||
args.push_back("big");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (!options.forceBinPlugin.isEmpty()) {
|
||||
args.push_back("-F");
|
||||
args.push_back(options.forceBinPlugin);
|
||||
}
|
||||
if (options.binLoadAddr != RVA_INVALID) {
|
||||
args.push_back("-B");
|
||||
args.push_back(RzAddressString(options.binLoadAddr));
|
||||
}
|
||||
if (options.mapAddr != RVA_INVALID) {
|
||||
args.push_back("-m");
|
||||
args.push_back(RzAddressString(options.mapAddr));
|
||||
}
|
||||
if (!options.filename.isEmpty()) {
|
||||
args.push_back(options.filename);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
bool CutterApplication::parseCommandLineOptions()
|
||||
{
|
||||
// Keep this function in sync with documentation
|
||||
@ -327,6 +398,27 @@ bool CutterApplication::parseCommandLineOptions()
|
||||
QObject::tr("level"));
|
||||
cmd_parser.addOption(analOption);
|
||||
|
||||
QCommandLineOption archOption({ "a", "arch" }, QObject::tr("Sets a specific architecture name"),
|
||||
QObject::tr("arch"));
|
||||
cmd_parser.addOption(archOption);
|
||||
|
||||
QCommandLineOption bitsOption({ "b", "bits" }, QObject::tr("Sets a specific architecture bits"),
|
||||
QObject::tr("bits"));
|
||||
cmd_parser.addOption(bitsOption);
|
||||
|
||||
QCommandLineOption cpuOption({ "c", "cpu" }, QObject::tr("Sets a specific CPU"),
|
||||
QObject::tr("cpu"));
|
||||
cmd_parser.addOption(cpuOption);
|
||||
|
||||
QCommandLineOption osOption({ "o", "os" }, QObject::tr("Sets a specific operating system"),
|
||||
QObject::tr("os"));
|
||||
cmd_parser.addOption(osOption);
|
||||
|
||||
QCommandLineOption endianOption({ "e", "endian" },
|
||||
QObject::tr("Sets the endianness (big or little)"),
|
||||
QObject::tr("big|little"));
|
||||
cmd_parser.addOption(endianOption);
|
||||
|
||||
QCommandLineOption formatOption({ "F", "format" },
|
||||
QObject::tr("Force using a specific file format (bin plugin)"),
|
||||
QObject::tr("name"));
|
||||
@ -337,6 +429,11 @@ bool CutterApplication::parseCommandLineOptions()
|
||||
QObject::tr("base address"));
|
||||
cmd_parser.addOption(baddrOption);
|
||||
|
||||
QCommandLineOption maddrOption({ "m", "map" },
|
||||
QObject::tr("Map the binary at a specific address"),
|
||||
QObject::tr("map address"));
|
||||
cmd_parser.addOption(maddrOption);
|
||||
|
||||
QCommandLineOption scriptOption("i", QObject::tr("Run script file"), QObject::tr("file"));
|
||||
cmd_parser.addOption(scriptOption);
|
||||
|
||||
@ -348,6 +445,10 @@ bool CutterApplication::parseCommandLineOptions()
|
||||
QObject::tr("Open file in write mode"));
|
||||
cmd_parser.addOption(writeModeOption);
|
||||
|
||||
QCommandLineOption phyModeOption({ "P", "phymode" },
|
||||
QObject::tr("Disables virtual addressing"));
|
||||
cmd_parser.addOption(phyModeOption);
|
||||
|
||||
QCommandLineOption pythonHomeOption(
|
||||
"pythonhome", QObject::tr("PYTHONHOME to use for embedded python interpreter"),
|
||||
"PYTHONHOME");
|
||||
@ -378,30 +479,30 @@ bool CutterApplication::parseCommandLineOptions()
|
||||
opts.args = cmd_parser.positionalArguments();
|
||||
|
||||
if (cmd_parser.isSet(analOption)) {
|
||||
bool analLevelSpecified = false;
|
||||
int analLevel = cmd_parser.value(analOption).toInt(&analLevelSpecified);
|
||||
bool analysisLevelSpecified = false;
|
||||
int analysisLevel = cmd_parser.value(analOption).toInt(&analysisLevelSpecified);
|
||||
|
||||
if (!analLevelSpecified || analLevel < 0 || analLevel > 2) {
|
||||
if (!analysisLevelSpecified || analysisLevel < 0 || analysisLevel > 2) {
|
||||
fprintf(stderr, "%s\n",
|
||||
QObject::tr("Invalid Analysis Level. May be a value between 0 and 2.")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
return false;
|
||||
}
|
||||
switch (analLevel) {
|
||||
switch (analysisLevel) {
|
||||
case 0:
|
||||
opts.analLevel = AutomaticAnalysisLevel::None;
|
||||
opts.analysisLevel = AutomaticAnalysisLevel::None;
|
||||
break;
|
||||
case 1:
|
||||
opts.analLevel = AutomaticAnalysisLevel::AAA;
|
||||
opts.analysisLevel = AutomaticAnalysisLevel::AAA;
|
||||
break;
|
||||
case 2:
|
||||
opts.analLevel = AutomaticAnalysisLevel::AAAA;
|
||||
opts.analysisLevel = AutomaticAnalysisLevel::AAAA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.args.empty() && opts.analLevel != AutomaticAnalysisLevel::Ask) {
|
||||
if (opts.args.empty() && opts.analysisLevel != AutomaticAnalysisLevel::Ask) {
|
||||
fprintf(stderr, "%s\n",
|
||||
QObject::tr("Filename must be specified to start analysis automatically.")
|
||||
.toLocal8Bit()
|
||||
@ -409,33 +510,67 @@ bool CutterApplication::parseCommandLineOptions()
|
||||
return false;
|
||||
}
|
||||
|
||||
InitialOptions options;
|
||||
if (!opts.args.isEmpty()) {
|
||||
opts.fileOpenOptions.filename = opts.args[0];
|
||||
opts.fileOpenOptions.forceBinPlugin = cmd_parser.value(formatOption);
|
||||
if (cmd_parser.isSet(baddrOption)) {
|
||||
bool ok;
|
||||
bool ok = false;
|
||||
RVA baddr = cmd_parser.value(baddrOption).toULongLong(&ok, 0);
|
||||
if (ok) {
|
||||
options.binLoadAddr = baddr;
|
||||
opts.fileOpenOptions.binLoadAddr = baddr;
|
||||
}
|
||||
}
|
||||
switch (opts.analLevel) {
|
||||
if (cmd_parser.isSet(maddrOption)) {
|
||||
bool ok = false;
|
||||
RVA maddr = cmd_parser.value(maddrOption).toULongLong(&ok, 0);
|
||||
if (ok) {
|
||||
opts.fileOpenOptions.mapAddr = maddr;
|
||||
}
|
||||
}
|
||||
switch (opts.analysisLevel) {
|
||||
case AutomaticAnalysisLevel::Ask:
|
||||
break;
|
||||
case AutomaticAnalysisLevel::None:
|
||||
opts.fileOpenOptions.analCmd = {};
|
||||
opts.fileOpenOptions.analysisCmd = {};
|
||||
break;
|
||||
case AutomaticAnalysisLevel::AAA:
|
||||
opts.fileOpenOptions.analCmd = { { "aaa", "Auto analysis" } };
|
||||
opts.fileOpenOptions.analysisCmd = { { "aaa", "Auto analysis" } };
|
||||
break;
|
||||
case AutomaticAnalysisLevel::AAAA:
|
||||
opts.fileOpenOptions.analCmd = { { "aaaa", "Auto analysis (experimental)" } };
|
||||
opts.fileOpenOptions.analysisCmd = { { "aaaa", "Auto analysis (experimental)" } };
|
||||
break;
|
||||
}
|
||||
opts.fileOpenOptions.script = cmd_parser.value(scriptOption);
|
||||
opts.fileOpenOptions.arch = cmd_parser.value(archOption);
|
||||
opts.fileOpenOptions.cpu = cmd_parser.value(cpuOption);
|
||||
opts.fileOpenOptions.os = cmd_parser.value(osOption);
|
||||
if (cmd_parser.isSet(bitsOption)) {
|
||||
bool ok = false;
|
||||
int bits = cmd_parser.value(bitsOption).toInt(&ok, 10);
|
||||
if (ok && bits > 0) {
|
||||
opts.fileOpenOptions.bits = bits;
|
||||
}
|
||||
}
|
||||
if (cmd_parser.isSet(endianOption)) {
|
||||
QString endian = cmd_parser.value(endianOption).toLower();
|
||||
opts.fileOpenOptions.endian = InitialOptions::Endianness::Auto;
|
||||
if (endian == "little") {
|
||||
opts.fileOpenOptions.endian = InitialOptions::Endianness::Little;
|
||||
} else if (endian == "big") {
|
||||
opts.fileOpenOptions.endian = InitialOptions::Endianness::Big;
|
||||
} else {
|
||||
fprintf(stderr, "%s\n",
|
||||
QObject::tr("Invalid Endianness. You can only set it to `big` or `little`.")
|
||||
.toLocal8Bit()
|
||||
.constData());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
opts.fileOpenOptions.endian = InitialOptions::Endianness::Auto;
|
||||
}
|
||||
|
||||
opts.fileOpenOptions.writeEnabled = cmd_parser.isSet(writeModeOption);
|
||||
opts.fileOpenOptions.useVA = !cmd_parser.isSet(phyModeOption);
|
||||
}
|
||||
|
||||
opts.fileOpenOptions.projectFile = cmd_parser.value(projectOption);
|
||||
|
@ -13,7 +13,7 @@ enum class AutomaticAnalysisLevel { Ask, None, AAA, AAAA };
|
||||
struct CutterCommandLineOptions
|
||||
{
|
||||
QStringList args;
|
||||
AutomaticAnalysisLevel analLevel = AutomaticAnalysisLevel::Ask;
|
||||
AutomaticAnalysisLevel analysisLevel = AutomaticAnalysisLevel::Ask;
|
||||
InitialOptions fileOpenOptions;
|
||||
QString pythonHome;
|
||||
bool outputRedirectionEnabled = true;
|
||||
@ -33,6 +33,10 @@ public:
|
||||
|
||||
void launchNewInstance(const QStringList &args = {});
|
||||
|
||||
InitialOptions getInitialOptions() const { return clOptions.fileOpenOptions; }
|
||||
void setInitialOptions(const InitialOptions &options) { clOptions.fileOpenOptions = options; }
|
||||
QStringList getArgs() const;
|
||||
|
||||
protected:
|
||||
bool event(QEvent *e);
|
||||
|
||||
@ -50,6 +54,7 @@ private:
|
||||
|
||||
private:
|
||||
bool m_FileAlreadyDropped;
|
||||
CutterCore core;
|
||||
MainWindow *mainWindow;
|
||||
CutterCommandLineOptions clOptions;
|
||||
};
|
||||
|
38
src/Main.cpp
38
src/Main.cpp
@ -3,7 +3,6 @@
|
||||
#include "core/MainWindow.h"
|
||||
#include "common/UpdateWorker.h"
|
||||
#include "CutterConfig.h"
|
||||
#include "common/CrashHandler.h"
|
||||
#include "common/SettingsUpgrade.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
@ -12,27 +11,30 @@
|
||||
|
||||
/**
|
||||
* @brief Attempt to connect to a parent console and configure outputs.
|
||||
*
|
||||
* @note Doesn't do anything if the exe wasn't executed from a console.
|
||||
*/
|
||||
#ifdef Q_OS_WIN
|
||||
#include <windows.h>
|
||||
|
||||
static void connectToConsole()
|
||||
{
|
||||
if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
|
||||
return;
|
||||
}
|
||||
BOOL attached = AttachConsole(ATTACH_PARENT_PROCESS);
|
||||
|
||||
// Avoid reconfiguring stderr/stdout if one of them is already connected to a stream.
|
||||
// Avoid reconfiguring stdin/stderr/stdout if one of them is already connected to a stream.
|
||||
// This can happen when running with stdout/stderr redirected to a file.
|
||||
if (0 > fileno(stdout)) {
|
||||
// Overwrite FD 1 and 2 for the benefit of any code that uses the FDs
|
||||
if (0 > fileno(stdin)) {
|
||||
// Overwrite FD 0, FD 1 and 2 for the benefit of any code that uses the FDs
|
||||
// directly. This is safe because the CRT allocates FDs 0, 1 and
|
||||
// 2 at startup even if they don't have valid underlying Windows
|
||||
// handles. This means we won't be overwriting an FD created by
|
||||
// _open() after startup.
|
||||
_close(0);
|
||||
|
||||
freopen(attached ? "CONIN$" : "NUL", "r+", stdin);
|
||||
}
|
||||
if (0 > fileno(stdout)) {
|
||||
_close(1);
|
||||
|
||||
if (freopen("CONOUT$", "a+", stdout)) {
|
||||
if (freopen(attached ? "CONOUT$" : "NUL", "a+", stdout)) {
|
||||
// Avoid buffering stdout/stderr since IOLBF is replaced by IOFBF in Win32.
|
||||
setvbuf(stdout, nullptr, _IONBF, 0);
|
||||
}
|
||||
@ -40,7 +42,7 @@ static void connectToConsole()
|
||||
if (0 > fileno(stderr)) {
|
||||
_close(2);
|
||||
|
||||
if (freopen("CONOUT$", "a+", stderr)) {
|
||||
if (freopen(attached ? "CONOUT$" : "NUL", "a+", stderr)) {
|
||||
setvbuf(stderr, nullptr, _IONBF, 0);
|
||||
}
|
||||
}
|
||||
@ -52,17 +54,6 @@ static void connectToConsole()
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef CUTTER_ENABLE_CRASH_REPORTS
|
||||
if (argc >= 3 && QString::fromLocal8Bit(argv[1]) == "--start-crash-handler") {
|
||||
QApplication app(argc, argv);
|
||||
QString dumpLocation = QString::fromLocal8Bit(argv[2]);
|
||||
showCrashDialog(dumpLocation);
|
||||
return 0;
|
||||
}
|
||||
|
||||
initCrashHandler();
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
connectToConsole();
|
||||
#endif
|
||||
@ -71,6 +62,9 @@ int main(int argc, char *argv[])
|
||||
qRegisterMetaType<QList<FunctionDescription>>();
|
||||
|
||||
QCoreApplication::setOrganizationName("rizin");
|
||||
#ifndef Q_OS_MACOS // don't set on macOS so that it doesn't affect config path there
|
||||
QCoreApplication::setOrganizationDomain("rizin.re");
|
||||
#endif
|
||||
QCoreApplication::setApplicationName("cutter");
|
||||
|
||||
// Importing settings after setting rename, needs separate handling in addition to regular version to version upgrade.
|
||||
|
@ -3,7 +3,7 @@
|
||||
generator-set = shiboken
|
||||
|
||||
header-file = ${BINDINGS_SRC_DIR}/bindings.h
|
||||
typesystem-file = ${BINDINGS_SRC_DIR}/bindings.xml
|
||||
typesystem-file = ${BINDINGS_BUILD_DIR}/bindings.xml
|
||||
|
||||
output-directory = ${BINDINGS_BUILD_DIR}
|
||||
|
||||
@ -14,4 +14,4 @@ typesystem-paths = ${PYSIDE_TYPESYSTEMS}
|
||||
enable-parent-ctor-heuristic
|
||||
enable-pyside-extensions
|
||||
enable-return-value-heuristic
|
||||
use-isnull-as-nb_nonzero
|
||||
use-isnull-as-nb_nonzero
|
||||
|
@ -30,7 +30,7 @@
|
||||
PyErr_Print();
|
||||
return QString();
|
||||
}
|
||||
PythonToCppFunc pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(SbkPySide2_QtCoreTypeConverters[SBK_QSTRING_IDX], pyResult);
|
||||
PythonToCppFunc pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(Sbk${PYSIDE_NAME}_QtCoreTypeConverters[SBK_QSTRING_IDX], pyResult);
|
||||
if (!pythonToCpp) {
|
||||
Shiboken::warning(PyExc_RuntimeWarning, 2, "Invalid return value for plugin metadata VAR_NAME, expected %s, got %s.", "QString", Py_TYPE(pyResult)->tp_name);
|
||||
return ::QString();
|
@ -9,7 +9,7 @@ script_path = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
|
||||
def get_cpp_files_gen(args, include_package=True):
|
||||
ts_tree = et.parse(os.path.join(script_path, "bindings.xml"))
|
||||
ts_tree = et.parse(os.path.join(script_path, "bindings.xml.in"))
|
||||
ts_root = ts_tree.getroot()
|
||||
|
||||
package = ts_root.attrib["package"]
|
||||
|
@ -13,11 +13,17 @@ AddressableFilterProxyModel::AddressableFilterProxyModel(AddressableItemModelI *
|
||||
|
||||
RVA AddressableFilterProxyModel::address(const QModelIndex &index) const
|
||||
{
|
||||
if (!addressableSourceModel) {
|
||||
return RVA_INVALID;
|
||||
}
|
||||
return addressableSourceModel->address(this->mapToSource(index));
|
||||
}
|
||||
|
||||
QString AddressableFilterProxyModel::name(const QModelIndex &index) const
|
||||
{
|
||||
if (!addressableSourceModel) {
|
||||
return QString();
|
||||
}
|
||||
return addressableSourceModel->name(this->mapToSource(index));
|
||||
}
|
||||
|
||||
@ -28,6 +34,6 @@ void AddressableFilterProxyModel::setSourceModel(QAbstractItemModel *)
|
||||
|
||||
void AddressableFilterProxyModel::setSourceModel(AddressableItemModelI *sourceModel)
|
||||
{
|
||||
ParentClass::setSourceModel(sourceModel->asItemModel());
|
||||
ParentClass::setSourceModel(sourceModel ? sourceModel->asItemModel() : nullptr);
|
||||
addressableSourceModel = sourceModel;
|
||||
}
|
||||
|
@ -1,32 +1,33 @@
|
||||
#include "core/Cutter.h"
|
||||
#include "common/AnalTask.h"
|
||||
#include "common/AnalysisTask.h"
|
||||
#include "core/MainWindow.h"
|
||||
#include "dialogs/InitialOptionsDialog.h"
|
||||
#include <QJsonArray>
|
||||
#include <QDebug>
|
||||
#include <QCheckBox>
|
||||
|
||||
AnalTask::AnalTask() : AsyncTask() {}
|
||||
AnalysisTask::AnalysisTask() : AsyncTask() {}
|
||||
|
||||
AnalTask::~AnalTask() {}
|
||||
AnalysisTask::~AnalysisTask() {}
|
||||
|
||||
void AnalTask::interrupt()
|
||||
void AnalysisTask::interrupt()
|
||||
{
|
||||
AsyncTask::interrupt();
|
||||
rz_cons_singleton()->context->breaked = true;
|
||||
}
|
||||
|
||||
QString AnalTask::getTitle()
|
||||
QString AnalysisTask::getTitle()
|
||||
{
|
||||
// If no file is loaded we consider it's Initial Analysis
|
||||
QJsonArray openedFiles = Core()->getOpenedFiles();
|
||||
if (!openedFiles.size()) {
|
||||
RzCoreLocked core(Core());
|
||||
RzList *descs = rz_id_storage_list(core->io->files);
|
||||
if (rz_list_empty(descs)) {
|
||||
return tr("Initial Analysis");
|
||||
}
|
||||
return tr("Analyzing Program");
|
||||
}
|
||||
|
||||
void AnalTask::runTask()
|
||||
void AnalysisTask::runTask()
|
||||
{
|
||||
int perms = RZ_PERM_RX;
|
||||
if (options.writeEnabled) {
|
||||
@ -38,8 +39,9 @@ void AnalTask::runTask()
|
||||
Core()->setConfig("bin.demangle", options.demangle);
|
||||
|
||||
// Do not reload the file if already loaded
|
||||
QJsonArray openedFiles = Core()->getOpenedFiles();
|
||||
if (!openedFiles.size() && options.filename.length()) {
|
||||
RzCoreLocked core(Core());
|
||||
RzList *descs = rz_id_storage_list(core->io->files);
|
||||
if (rz_list_empty(descs) && options.filename.length()) {
|
||||
log(tr("Loading the file..."));
|
||||
openFailed = false;
|
||||
bool fileLoaded =
|
||||
@ -62,7 +64,8 @@ void AnalTask::runTask()
|
||||
}
|
||||
|
||||
if (!options.os.isNull()) {
|
||||
Core()->cmdRaw("e asm.os=" + options.os);
|
||||
RzCoreLocked core(Core());
|
||||
rz_config_set(core->config, "asm.os", options.os.toUtf8().constData());
|
||||
}
|
||||
|
||||
if (!options.pdbFile.isNull()) {
|
||||
@ -76,14 +79,14 @@ void AnalTask::runTask()
|
||||
|
||||
if (!options.shellcode.isNull() && options.shellcode.size() / 2 > 0) {
|
||||
log(tr("Loading shellcode..."));
|
||||
Core()->cmdRaw("wx " + options.shellcode);
|
||||
rz_core_write_hexpair(core, core->offset, options.shellcode.toStdString().c_str());
|
||||
}
|
||||
|
||||
if (options.endian != InitialOptions::Endianness::Auto) {
|
||||
Core()->setEndianness(options.endian == InitialOptions::Endianness::Big);
|
||||
}
|
||||
|
||||
Core()->cmdRaw("fs *");
|
||||
rz_flag_space_set(core->flags, "*");
|
||||
|
||||
if (!options.script.isNull()) {
|
||||
log(tr("Executing script..."));
|
||||
@ -94,9 +97,9 @@ void AnalTask::runTask()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!options.analCmd.empty()) {
|
||||
if (!options.analysisCmd.empty()) {
|
||||
log(tr("Executing analysis..."));
|
||||
for (const CommandDescription &cmd : options.analCmd) {
|
||||
for (const CommandDescription &cmd : options.analysisCmd) {
|
||||
if (isInterrupted()) {
|
||||
return;
|
||||
}
|
@ -9,13 +9,13 @@ class CutterCore;
|
||||
class MainWindow;
|
||||
class InitialOptionsDialog;
|
||||
|
||||
class AnalTask : public AsyncTask
|
||||
class AnalysisTask : public AsyncTask
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AnalTask();
|
||||
~AnalTask();
|
||||
explicit AnalysisTask();
|
||||
~AnalysisTask();
|
||||
|
||||
QString getTitle() override;
|
||||
|
@ -2,21 +2,14 @@
|
||||
|
||||
BasicBlockHighlighter::BasicBlockHighlighter() {}
|
||||
|
||||
BasicBlockHighlighter::~BasicBlockHighlighter()
|
||||
{
|
||||
for (BasicBlockIt itr = bbMap.begin(); itr != bbMap.end(); ++itr) {
|
||||
delete itr->second;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Highlight the basic block at address
|
||||
*/
|
||||
void BasicBlockHighlighter::highlight(RVA address, const QColor &color)
|
||||
{
|
||||
BasicBlock *block = new BasicBlock;
|
||||
block->address = address;
|
||||
block->color = color;
|
||||
BasicBlock block;
|
||||
block.address = address;
|
||||
block.color = color;
|
||||
bbMap[address] = block;
|
||||
}
|
||||
|
||||
@ -33,13 +26,11 @@ void BasicBlockHighlighter::clear(RVA address)
|
||||
*
|
||||
* If there is nothing to highlight at specified address, returns nullptr
|
||||
*/
|
||||
BasicBlock *BasicBlockHighlighter::getBasicBlock(RVA address)
|
||||
BasicBlockHighlighter::BasicBlock *BasicBlockHighlighter::getBasicBlock(RVA address)
|
||||
{
|
||||
BasicBlockIt it;
|
||||
|
||||
it = bbMap.find(address);
|
||||
auto it = bbMap.find(address);
|
||||
if (it != bbMap.end()) {
|
||||
return it->second;
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@ -6,26 +6,23 @@ class BasicBlockHighlighter;
|
||||
#include "Cutter.h"
|
||||
#include <map>
|
||||
|
||||
struct BasicBlock
|
||||
{
|
||||
RVA address;
|
||||
QColor color;
|
||||
};
|
||||
|
||||
typedef std::map<RVA, BasicBlock *>::iterator BasicBlockIt;
|
||||
|
||||
class BasicBlockHighlighter
|
||||
{
|
||||
public:
|
||||
struct BasicBlock
|
||||
{
|
||||
RVA address;
|
||||
QColor color;
|
||||
};
|
||||
|
||||
BasicBlockHighlighter();
|
||||
~BasicBlockHighlighter();
|
||||
|
||||
void highlight(RVA address, const QColor &color);
|
||||
void clear(RVA address);
|
||||
BasicBlock *getBasicBlock(RVA address);
|
||||
|
||||
private:
|
||||
std::map<RVA, BasicBlock *> bbMap;
|
||||
std::map<RVA, BasicBlock> bbMap;
|
||||
};
|
||||
|
||||
#endif // BASICBLOCKHIGHLIGHTER_H
|
||||
|
@ -8,38 +8,35 @@
|
||||
|
||||
void openIssue()
|
||||
{
|
||||
RzCoreLocked core(Core());
|
||||
RzBinFile *bf = rz_bin_cur(core->bin);
|
||||
RzBinInfo *info = rz_bin_get_info(core->bin);
|
||||
RzBinPlugin *plugin = rz_bin_file_cur_plugin(bf);
|
||||
|
||||
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";
|
||||
}
|
||||
format = plugin && RZ_STR_ISNOTEMPTY(plugin->name) ? plugin->name : "N/A";
|
||||
arch = info && RZ_STR_ISNOTEMPTY(info->arch) ? info->arch : "N/A";
|
||||
type = info && RZ_STR_ISNOTEMPTY(info->type) ? info->type : "N/A";
|
||||
url = "https://github.com/rizinorg/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"
|
||||
+ osInfo + "\n* Cutter version: " + CUTTER_VERSION_FULL + "\n* Obtained from:\n"
|
||||
+ " - [ ] Built from source\n - [ ] Downloaded release from Cutter website or GitHub "
|
||||
"\n"
|
||||
" - [ ] Distribution repository\n* File format: "
|
||||
+ format + "\n * Arch: " + arch + "\n * Type: " + type
|
||||
+ "\n\n**Describe the bug**\n\n<!-- A clear and concise description of what the bug "
|
||||
"is. -->"
|
||||
"\n\n**To Reproduce**\n\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.";
|
||||
"4. See error\n\n**Expected behavior**\n\n"
|
||||
"<!-- A clear and concise description of what you expected to happen. -->\n\n\n"
|
||||
"**Screenshots**\n\n<!-- If applicable, add screenshots to help explain your "
|
||||
"problem. -->\n\n\n"
|
||||
"**Additional context**\n\n<!-- Add any other context about the problem here. -->\n";
|
||||
|
||||
QDesktopServices::openUrl(QUrl(url, QUrl::TolerantMode));
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <QJsonArray>
|
||||
#include <QStandardPaths>
|
||||
#include <QRegularExpression>
|
||||
#include <rz_util/rz_path.h>
|
||||
|
||||
#include "common/Configuration.h"
|
||||
|
||||
@ -29,16 +30,15 @@ const QStringList ColorThemeWorker::rizinUnusedOptions = {
|
||||
|
||||
ColorThemeWorker::ColorThemeWorker(QObject *parent) : QObject(parent)
|
||||
{
|
||||
char *szThemes = rz_str_home(RZ_HOME_THEMES);
|
||||
char *szThemes = rz_path_home_prefix(RZ_THEMES);
|
||||
customRzThemesLocationPath = szThemes;
|
||||
rz_mem_free(szThemes);
|
||||
if (!QDir(customRzThemesLocationPath).exists()) {
|
||||
QDir().mkpath(customRzThemesLocationPath);
|
||||
}
|
||||
|
||||
QDir currDir {
|
||||
QStringLiteral("%1%2%3").arg(rz_sys_prefix(nullptr)).arg(RZ_SYS_DIR).arg(RZ_THEMES)
|
||||
};
|
||||
char *theme_dir = rz_path_prefix(RZ_THEMES);
|
||||
QDir currDir { theme_dir };
|
||||
if (currDir.exists()) {
|
||||
standardRzThemesLocationPath = currDir.absolutePath();
|
||||
} else {
|
||||
@ -47,6 +47,7 @@ ColorThemeWorker::ColorThemeWorker(QObject *parent) : QObject(parent)
|
||||
"Most likely, Rizin is not properly installed.")
|
||||
.arg(currDir.path()));
|
||||
}
|
||||
free(theme_dir);
|
||||
}
|
||||
|
||||
QColor ColorThemeWorker::mergeColors(const QColor &upper, const QColor &lower) const
|
||||
@ -77,27 +78,15 @@ QString ColorThemeWorker::copy(const QString &srcThemeName, const QString ©T
|
||||
return save(getTheme(srcThemeName), copyThemeName);
|
||||
}
|
||||
|
||||
QString ColorThemeWorker::save(const QJsonDocument &theme, const QString &themeName) const
|
||||
QString ColorThemeWorker::save(const Theme &theme, const QString &themeName) const
|
||||
{
|
||||
QFile fOut(QDir(customRzThemesLocationPath).filePath(themeName));
|
||||
if (!fOut.open(QFile::WriteOnly | QFile::Truncate)) {
|
||||
return tr("The file <b>%1</b> cannot be opened.").arg(QFileInfo(fOut).filePath());
|
||||
}
|
||||
|
||||
QJsonObject obj = theme.object();
|
||||
for (auto it = obj.constBegin(); it != obj.constEnd(); it++) {
|
||||
|
||||
QJsonArray arr = it.value().toArray();
|
||||
QColor color;
|
||||
if (arr.isEmpty()) {
|
||||
color = it.value().toVariant().value<QColor>();
|
||||
} else if (arr.size() == 4) {
|
||||
color = QColor(arr[0].toInt(), arr[1].toInt(), arr[2].toInt(), arr[3].toInt());
|
||||
} else if (arr.size() == 3) {
|
||||
color = QColor(arr[0].toInt(), arr[1].toInt(), arr[2].toInt());
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
for (auto it = theme.constBegin(); it != theme.constEnd(); it++) {
|
||||
const QColor &color = it.value();
|
||||
if (cutterSpecificOptions.contains(it.key())) {
|
||||
fOut.write(QString("#~%1 rgb:%2\n")
|
||||
.arg(it.key(), color.name(QColor::HexArgb).remove('#'))
|
||||
@ -124,24 +113,18 @@ bool ColorThemeWorker::isThemeExist(const QString &name) const
|
||||
return themes.contains(name);
|
||||
}
|
||||
|
||||
QJsonDocument ColorThemeWorker::getTheme(const QString &themeName) const
|
||||
ColorThemeWorker::Theme ColorThemeWorker::getTheme(const QString &themeName) const
|
||||
{
|
||||
int r, g, b, a;
|
||||
QVariantMap theme;
|
||||
Theme theme;
|
||||
QString curr = Config()->getColorTheme();
|
||||
|
||||
if (themeName != curr) {
|
||||
Core()->cmdRaw(QString("eco %1").arg(themeName));
|
||||
theme = Core()->cmdj("ecj").object().toVariantMap();
|
||||
Core()->cmdRaw(QString("eco %1").arg(curr));
|
||||
RzCoreLocked core(Core());
|
||||
rz_core_theme_load(core, themeName.toUtf8().constData());
|
||||
theme = Core()->getTheme();
|
||||
rz_core_theme_load(core, curr.toUtf8().constData());
|
||||
} else {
|
||||
theme = Core()->cmdj("ecj").object().toVariantMap();
|
||||
}
|
||||
|
||||
for (auto it = theme.begin(); it != theme.end(); it++) {
|
||||
auto arr = it.value().toList();
|
||||
QColor(arr[0].toInt(), arr[1].toInt(), arr[2].toInt()).getRgb(&r, &g, &b, &a);
|
||||
theme[it.key()] = QJsonArray({ r, g, b, a });
|
||||
theme = Core()->getTheme();
|
||||
}
|
||||
|
||||
ColorFlags colorFlags = ColorFlags::DarkFlag;
|
||||
@ -150,14 +133,13 @@ QJsonDocument ColorThemeWorker::getTheme(const QString &themeName) const
|
||||
}
|
||||
|
||||
for (auto &it : cutterSpecificOptions) {
|
||||
Configuration::cutterOptionColors[it][colorFlags].getRgb(&r, &g, &b, &a);
|
||||
theme.insert(it, QJsonArray { r, g, b, a });
|
||||
theme.insert(it, QColor(Configuration::cutterOptionColors[it][colorFlags]));
|
||||
}
|
||||
|
||||
if (isCustomTheme(themeName)) {
|
||||
QFile src(QDir(customRzThemesLocationPath).filePath(themeName));
|
||||
if (!src.open(QFile::ReadOnly)) {
|
||||
return QJsonDocument();
|
||||
return {};
|
||||
}
|
||||
QStringList sl;
|
||||
for (auto &line : QString(src.readAll()).split('\n', CUTTER_QT_SKIP_EMPTY_PARTS)) {
|
||||
@ -167,8 +149,7 @@ QJsonDocument ColorThemeWorker::getTheme(const QString &themeName) const
|
||||
if (sl.size() != 3 || sl[0][0] == '#') {
|
||||
continue;
|
||||
}
|
||||
QColor(sl[2]).getRgb(&r, &g, &b, &a);
|
||||
theme.insert(sl[1], QJsonArray({ r, g, b, a }));
|
||||
theme.insert(sl[1], QColor(sl[2]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,21 +157,7 @@ QJsonDocument ColorThemeWorker::getTheme(const QString &themeName) const
|
||||
theme.remove(key);
|
||||
}
|
||||
|
||||
// manualy converting instead of using QJsonObject::fromVariantMap because
|
||||
// Qt < 5.6 QJsonValue.fromVariant doesn't expect QVariant to already contain
|
||||
// QJson values like QJsonArray.
|
||||
// https://github.com/qt/qtbase/commit/26237f0a2d8db80024b601f676bbce54d483e672
|
||||
QJsonObject obj;
|
||||
for (auto it = theme.begin(); it != theme.end(); it++) {
|
||||
auto &value = it.value();
|
||||
if (value.canConvert<QJsonArray>()) {
|
||||
obj[it.key()] = it.value().value<QJsonArray>();
|
||||
} else {
|
||||
obj[it.key()] = QJsonValue::fromVariant(value);
|
||||
}
|
||||
}
|
||||
|
||||
return QJsonDocument(obj);
|
||||
return theme;
|
||||
}
|
||||
|
||||
QString ColorThemeWorker::deleteTheme(const QString &themeName) const
|
||||
@ -276,13 +243,11 @@ bool ColorThemeWorker::isFileTheme(const QString &filePath, bool *ok) const
|
||||
}
|
||||
|
||||
const QString colors = "black|red|white|green|magenta|yellow|cyan|blue|gray|none";
|
||||
QString options = (Core()->cmdj("ecj").object().keys() << cutterSpecificOptions)
|
||||
.join('|')
|
||||
.replace(".", "\\.");
|
||||
QString options =
|
||||
(Core()->getThemeKeys() << cutterSpecificOptions).join('|').replace(".", "\\.");
|
||||
|
||||
QString pattern = QString("((ec\\s+(%1)\\s+(((rgb:|#)[0-9a-fA-F]{3,8})|(%2))))\\s*")
|
||||
.arg(options)
|
||||
.arg(colors);
|
||||
QString pattern =
|
||||
QString("((ec\\s+(%1)\\s+(((rgb:|#)[0-9a-fA-F]{3,8})|(%2))))\\s*").arg(options, colors);
|
||||
// The below construct mimics the behaviour of QRegexP::exactMatch(), which was here before
|
||||
QRegularExpression regexp("\\A(?:" + pattern + ")\\z");
|
||||
|
||||
@ -313,7 +278,7 @@ QStringList ColorThemeWorker::customThemes() const
|
||||
const QStringList &ColorThemeWorker::getRizinSpecificOptions()
|
||||
{
|
||||
if (rizinSpecificOptions.isEmpty()) {
|
||||
rizinSpecificOptions = Core()->cmdj("ecj").object().keys();
|
||||
rizinSpecificOptions << Core()->getThemeKeys();
|
||||
}
|
||||
return rizinSpecificOptions;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <QColor>
|
||||
#include <QObject>
|
||||
#include "Cutter.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
|
||||
#define ThemeWorker() (ColorThemeWorker::instance())
|
||||
@ -17,6 +18,8 @@ class ColorThemeWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
typedef QHash<QString, QColor> Theme;
|
||||
|
||||
/**
|
||||
* @brief cutterSpecificOptions is list of all available Cutter-only color options.
|
||||
*/
|
||||
@ -53,7 +56,7 @@ public:
|
||||
* Name of theme to save.
|
||||
* @return "" on success or error message.
|
||||
*/
|
||||
QString save(const QJsonDocument &theme, const QString &themeName) const;
|
||||
QString save(const Theme &theme, const QString &themeName) const;
|
||||
|
||||
/**
|
||||
* @brief Returns whether or not @a themeName theme is custom (created by user or imported) or
|
||||
@ -70,12 +73,11 @@ public:
|
||||
bool isThemeExist(const QString &name) const;
|
||||
|
||||
/**
|
||||
* @brief Returns theme as Json where key is option name and value is array of 3 Ints (Red,
|
||||
* Green, Blue).
|
||||
* @brief Returns theme as QHash where key is option name and value is QColor.
|
||||
* @param themeName
|
||||
* Theme to get.
|
||||
*/
|
||||
QJsonDocument getTheme(const QString &themeName) const;
|
||||
Theme getTheme(const QString &themeName) const;
|
||||
|
||||
/**
|
||||
* @brief Deletes theme named @a themeName.
|
||||
|
@ -7,9 +7,9 @@
|
||||
#include <QApplication>
|
||||
|
||||
#ifdef CUTTER_ENABLE_KSYNTAXHIGHLIGHTING
|
||||
# include <KSyntaxHighlighting/repository.h>
|
||||
# include <KSyntaxHighlighting/theme.h>
|
||||
# include <KSyntaxHighlighting/definition.h>
|
||||
# include <KSyntaxHighlighting/Repository>
|
||||
# include <KSyntaxHighlighting/Theme>
|
||||
# include <KSyntaxHighlighting/Definition>
|
||||
#endif
|
||||
|
||||
#include "common/ColorThemeWorker.h"
|
||||
@ -21,10 +21,16 @@
|
||||
* and for light - only light ones.
|
||||
*/
|
||||
const QHash<QString, ColorFlags> Configuration::relevantThemes = {
|
||||
{ "ayu", DarkFlag }, { "consonance", DarkFlag }, { "darkda", DarkFlag },
|
||||
{ "onedark", DarkFlag }, { "solarized", DarkFlag }, { "zenburn", DarkFlag },
|
||||
{ "cutter", LightFlag }, { "dark", LightFlag }, { "matrix", LightFlag },
|
||||
{ "tango", LightFlag }, { "white", LightFlag }
|
||||
{ "ayu", DarkFlag }, { "basic", DarkFlag }, { "behelit", DarkFlag },
|
||||
{ "bold", DarkFlag }, { "bright", DarkFlag }, { "consonance", DarkFlag },
|
||||
{ "darkda", DarkFlag }, { "defragger", DarkFlag }, { "focus", DarkFlag },
|
||||
{ "gentoo", DarkFlag }, { "lima", DarkFlag }, { "monokai", DarkFlag },
|
||||
{ "ogray", DarkFlag }, { "onedark", DarkFlag }, { "pink", DarkFlag },
|
||||
{ "rasta", DarkFlag }, { "sepia", DarkFlag }, { "smyck", DarkFlag },
|
||||
{ "solarized", DarkFlag }, { "twilight", DarkFlag }, { "white2", DarkFlag },
|
||||
{ "xvilka", DarkFlag }, { "zenburn", DarkFlag }, { "cga", LightFlag },
|
||||
{ "cutter", LightFlag }, { "dark", LightFlag }, { "gb", LightFlag },
|
||||
{ "matrix", LightFlag }, { "tango", LightFlag }, { "white", LightFlag }
|
||||
};
|
||||
static const QString DEFAULT_LIGHT_COLOR_THEME = "cutter";
|
||||
static const QString DEFAULT_DARK_COLOR_THEME = "ayu";
|
||||
@ -39,7 +45,9 @@ const QHash<QString, QHash<ColorFlags, QColor>> Configuration::cutterOptionColor
|
||||
{ "gui.item_invalid",
|
||||
{ { DarkFlag, QColor(0x9b, 0x9b, 0x9b) }, { LightFlag, QColor(0x9b, 0x9b, 0x9b) } } },
|
||||
{ "gui.main",
|
||||
{ { DarkFlag, QColor(0x00, 0x80, 0x00) }, { LightFlag, QColor(0x00, 0x80, 0x00) } } },
|
||||
{ { DarkFlag, QColor(0x21, 0xd8, 0x93) }, { LightFlag, QColor(0x00, 0x80, 0x00) } } },
|
||||
{ "gui.flirt",
|
||||
{ { DarkFlag, QColor(0xd8, 0xbb, 0x21) }, { LightFlag, QColor(0xf1, 0xc4, 0x0f) } } },
|
||||
{ "gui.item_unsafe",
|
||||
{ { DarkFlag, QColor(0xff, 0x81, 0x7b) }, { LightFlag, QColor(0xff, 0x81, 0x7b) } } },
|
||||
{ "gui.navbar.seek",
|
||||
@ -135,8 +143,8 @@ Configuration::Configuration() : QObject(), nativePalette(qApp->palette())
|
||||
mPtr = this;
|
||||
if (!s.isWritable()) {
|
||||
QMessageBox::critical(
|
||||
nullptr, tr("Critical!"),
|
||||
tr("!!! Settings are not writable! Make sure you have a write access to \"%1\"")
|
||||
nullptr, tr("Critical Error!"),
|
||||
tr("Settings are not writable! Make sure you have a write access to \"%1\".")
|
||||
.arg(s.fileName()));
|
||||
}
|
||||
#ifdef CUTTER_ENABLE_KSYNTAXHIGHLIGHTING
|
||||
@ -193,7 +201,6 @@ void Configuration::resetAll()
|
||||
{
|
||||
// Don't reset all rizin vars, that currently breaks a bunch of stuff.
|
||||
// settingsFile.remove()+loadInitials() should reset all settings configurable using Cutter GUI.
|
||||
// Core()->cmdRaw("e-");
|
||||
|
||||
Core()->setSettings();
|
||||
// Delete the file so no extra configuration is in it.
|
||||
@ -244,8 +251,8 @@ bool Configuration::setLocaleByName(const QString &language)
|
||||
QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry);
|
||||
|
||||
for (auto &it : allLocales) {
|
||||
if (QString::compare(it.nativeLanguageName(), language, Qt::CaseInsensitive) == 0 ||
|
||||
it.name() == language) {
|
||||
if (QString::compare(it.nativeLanguageName(), language, Qt::CaseInsensitive) == 0
|
||||
|| it.name() == language) {
|
||||
setLocale(it);
|
||||
return true;
|
||||
}
|
||||
@ -281,6 +288,15 @@ void Configuration::loadNativeStylesheet()
|
||||
f.open(QFile::ReadOnly | QFile::Text);
|
||||
QTextStream ts(&f);
|
||||
QString stylesheet = ts.readAll();
|
||||
#ifdef Q_OS_MACOS
|
||||
QFile mf(nativeWindowIsDark() ? ":native/native-macos-dark.qss"
|
||||
: ":native/native-macos-light.qss");
|
||||
if (mf.exists()) {
|
||||
mf.open(QFile::ReadOnly | QFile::Text);
|
||||
QTextStream mts(&mf);
|
||||
stylesheet += "\n" + mts.readAll();
|
||||
}
|
||||
#endif
|
||||
qApp->setStyleSheet(stylesheet);
|
||||
}
|
||||
|
||||
@ -512,20 +528,16 @@ const QColor Configuration::getColor(const QString &name) const
|
||||
void Configuration::setColorTheme(const QString &theme)
|
||||
{
|
||||
if (theme == "default") {
|
||||
Core()->cmdRaw("ecd");
|
||||
rz_cons_pal_init(Core()->core()->cons->context);
|
||||
s.setValue("theme", "default");
|
||||
} else {
|
||||
Core()->cmdRaw(QStringLiteral("eco %1").arg(theme));
|
||||
rz_core_theme_load(Core()->core(), theme.toUtf8().constData());
|
||||
s.setValue("theme", theme);
|
||||
}
|
||||
|
||||
QJsonObject colorTheme = ThemeWorker().getTheme(theme).object();
|
||||
ColorThemeWorker::Theme colorTheme = ThemeWorker().getTheme(theme);
|
||||
for (auto it = colorTheme.constBegin(); it != colorTheme.constEnd(); it++) {
|
||||
QJsonArray rgb = it.value().toArray();
|
||||
if (rgb.size() != 4) {
|
||||
continue;
|
||||
}
|
||||
setColor(it.key(), QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt(), rgb[3].toInt()));
|
||||
setColor(it.key(), it.value());
|
||||
}
|
||||
|
||||
emit colorsUpdated();
|
||||
@ -652,11 +664,13 @@ QStringList Configuration::getAvailableTranslations()
|
||||
|
||||
for (auto i : fileNames) {
|
||||
QString localeName = i.mid(sizeof("cutter_") - 1, 2); // TODO:#2321 don't asume 2 characters
|
||||
// language code is sometimes 3 characters, and there could also be language_COUNTRY. Qt supports that.
|
||||
// language code is sometimes 3 characters, and there could also be language_COUNTRY. Qt
|
||||
// supports that.
|
||||
QLocale locale(localeName);
|
||||
if (locale.language() != QLocale::C) {
|
||||
currLanguageName = locale.nativeLanguageName();
|
||||
if (currLanguageName.isEmpty()) { // Qt doesn't have native language name for some languages
|
||||
if (currLanguageName
|
||||
.isEmpty()) { // Qt doesn't have native language name for some languages
|
||||
currLanguageName = QLocale::languageToString(locale.language());
|
||||
}
|
||||
if (!currLanguageName.isEmpty()) {
|
||||
@ -759,6 +773,16 @@ bool Configuration::getOutputRedirectionEnabled() const
|
||||
return outputRedirectEnabled;
|
||||
}
|
||||
|
||||
void Configuration::setPreviewValue(bool checked)
|
||||
{
|
||||
s.setValue("asm.preview", checked);
|
||||
}
|
||||
|
||||
bool Configuration::getPreviewValue() const
|
||||
{
|
||||
return s.value("asm.preview").toBool();
|
||||
}
|
||||
|
||||
bool Configuration::getGraphBlockEntryOffset()
|
||||
{
|
||||
return s.value("graphBlockEntryOffset", true).value<bool>();
|
||||
@ -796,3 +820,13 @@ void Configuration::addRecentProject(QString file)
|
||||
files.prepend(file);
|
||||
setRecentProjects(files);
|
||||
}
|
||||
|
||||
QString Configuration::getFunctionsWidgetLayout()
|
||||
{
|
||||
return s.value("functionsWidgetLayout").toString();
|
||||
}
|
||||
|
||||
void Configuration::setFunctionsWidgetLayout(const QString &layout)
|
||||
{
|
||||
s.setValue("functionsWidgetLayout", layout);
|
||||
}
|
||||
|
@ -167,6 +167,17 @@ public:
|
||||
|
||||
void setGraphMinFontSize(int sz) { s.setValue("graph.minfontsize", sz); }
|
||||
|
||||
/**
|
||||
* @brief Get the boolean setting for preview in Graph
|
||||
* @return True if preview checkbox is checked, false otherwise
|
||||
*/
|
||||
bool getGraphPreview() { return s.value("graph.preview").toBool(); }
|
||||
/**
|
||||
* @brief Set the boolean setting for preview in Graph
|
||||
* @param checked is a boolean that represents the preview checkbox
|
||||
*/
|
||||
void setGraphPreview(bool checked) { s.setValue("graph.preview", checked); }
|
||||
|
||||
/**
|
||||
* @brief Getters and setters for the transaparent option state and scale factor for bitmap
|
||||
* graph exports.
|
||||
@ -201,6 +212,9 @@ public:
|
||||
void setOutputRedirectionEnabled(bool enabled);
|
||||
bool getOutputRedirectionEnabled() const;
|
||||
|
||||
void setPreviewValue(bool checked);
|
||||
bool getPreviewValue() const;
|
||||
|
||||
/**
|
||||
* @brief Recently opened binaries, as shown in NewFileDialog.
|
||||
*/
|
||||
@ -214,6 +228,19 @@ public:
|
||||
void setRecentProjects(const QStringList &list);
|
||||
void addRecentProject(QString file);
|
||||
|
||||
// Functions Widget Layout
|
||||
|
||||
/**
|
||||
* @brief Get the layout of the Functions widget.
|
||||
* @return The layout.
|
||||
*/
|
||||
QString getFunctionsWidgetLayout();
|
||||
|
||||
/**
|
||||
* @brief Set the layout of the Functions widget
|
||||
* @param layout The layout of the Functions widget, either horizontal or vertical.
|
||||
*/
|
||||
void setFunctionsWidgetLayout(const QString &layout);
|
||||
public slots:
|
||||
void refreshFont();
|
||||
signals:
|
||||
|
@ -1,163 +0,0 @@
|
||||
#include "CrashHandler.h"
|
||||
#include "BugReporting.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QFileDialog>
|
||||
#include <QStandardPaths>
|
||||
#include <QTime>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QMap>
|
||||
#include <QProcess>
|
||||
|
||||
#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
|
||||
|
||||
static google_breakpad::ExceptionHandler *exceptionHandler = nullptr;
|
||||
|
||||
static void finishCrashHandler()
|
||||
{
|
||||
delete exceptionHandler;
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
const QDir dir = QString::fromWCharArray(_dump_dir);
|
||||
const QString id = QString::fromWCharArray(_minidump_id);
|
||||
QProcess::startDetached(QCoreApplication::applicationFilePath(),
|
||||
{ "--start-crash-handler", dir.filePath(id + ".dmp") });
|
||||
_exit(1);
|
||||
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)
|
||||
{
|
||||
QProcess::startDetached(QCoreApplication::applicationFilePath(),
|
||||
{ "--start-crash-handler", md.path() });
|
||||
_exit(1);
|
||||
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)
|
||||
{
|
||||
const QDir dir = QString::fromUtf8(dump_dir);
|
||||
const QString id = QString::fromUtf8(minidump_id);
|
||||
QProcess::startDetached(QCoreApplication::applicationFilePath(),
|
||||
{ "--start-crash-handler", dir.filePath(id + ".dmp") });
|
||||
_exit(1);
|
||||
return true;
|
||||
}
|
||||
#endif // Q_OS
|
||||
|
||||
void initCrashHandler()
|
||||
{
|
||||
if (exceptionHandler) {
|
||||
return;
|
||||
}
|
||||
// Here will be placed crash dump at the first place
|
||||
// and then moved if needed
|
||||
|
||||
#if defined(Q_OS_LINUX)
|
||||
static std::string tmpLocation =
|
||||
QStandardPaths::writableLocation(QStandardPaths::TempLocation).toStdString();
|
||||
exceptionHandler = new google_breakpad::ExceptionHandler(
|
||||
google_breakpad::MinidumpDescriptor(tmpLocation), nullptr, callback, nullptr, true, -1);
|
||||
#elif defined(Q_OS_MACOS)
|
||||
static std::string tmpLocation =
|
||||
QStandardPaths::writableLocation(QStandardPaths::TempLocation).toStdString();
|
||||
exceptionHandler = new google_breakpad::ExceptionHandler(tmpLocation, nullptr, callback,
|
||||
nullptr, true, nullptr);
|
||||
#else
|
||||
static std::wstring tmpLocation =
|
||||
QStandardPaths::writableLocation(QStandardPaths::TempLocation).toStdWString();
|
||||
exceptionHandler =
|
||||
new google_breakpad::ExceptionHandler(tmpLocation, nullptr, callback, nullptr,
|
||||
google_breakpad::ExceptionHandler::HANDLER_ALL);
|
||||
#endif
|
||||
atexit(finishCrashHandler);
|
||||
}
|
||||
|
||||
void showCrashDialog(const QString &dumpFile)
|
||||
{
|
||||
QMessageBox mb;
|
||||
mb.setWindowTitle(QObject::tr("Crash"));
|
||||
mb.setText(QObject::tr("Cutter received a signal it can't handle and will close.<br/>"
|
||||
"Would you like to create a crash dump for a bug report?"));
|
||||
mb.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
mb.button(QMessageBox::Yes)->setText(QObject::tr("Create a Crash Dump"));
|
||||
mb.button(QMessageBox::No)->setText(QObject::tr("Quit"));
|
||||
mb.setDefaultButton(QMessageBox::Yes);
|
||||
|
||||
bool ok = false;
|
||||
int ret = mb.exec();
|
||||
if (ret == QMessageBox::Yes) {
|
||||
QString dumpSaveFileName;
|
||||
int placementFailCounter = 0;
|
||||
do {
|
||||
placementFailCounter++;
|
||||
if (placementFailCounter == 4) {
|
||||
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("HH.mm.ss") + ".dmp",
|
||||
QObject::tr("Minidump (*.dmp)"));
|
||||
|
||||
if (dumpSaveFileName.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (QFile::rename(dumpFile, dumpSaveFileName)) {
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
QMessageBox::critical(nullptr, QObject::tr("Save Crash Dump"),
|
||||
QObject::tr("Failed to write to %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("Quit"));
|
||||
info.setDefaultButton(QMessageBox::Yes);
|
||||
|
||||
int ret = info.exec();
|
||||
if (ret == QMessageBox::Yes) {
|
||||
openIssue();
|
||||
}
|
||||
} else {
|
||||
QMessageBox::critical(nullptr, QObject::tr("Error"),
|
||||
QObject::tr("Error occurred during crash dump creation."));
|
||||
}
|
||||
} else {
|
||||
QFile f(dumpFile);
|
||||
f.remove();
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
#ifndef CRASH_HANDLER_H
|
||||
#define CRASH_HANDLER_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
/**
|
||||
* @fn void initCrashHandler()
|
||||
*
|
||||
* If CUTTER_ENABLE_CRASH_REPORTS is true, initializes
|
||||
* crash handling and reporting, otherwise does nothing.
|
||||
*/
|
||||
void initCrashHandler();
|
||||
|
||||
void showCrashDialog(const QString &dumpFile);
|
||||
|
||||
#endif // CRASH_HANDLER_H
|
@ -13,18 +13,18 @@ CutterSeekable::~CutterSeekable() {}
|
||||
void CutterSeekable::setSynchronization(bool sync)
|
||||
{
|
||||
synchronized = sync;
|
||||
onCoreSeekChanged(Core()->getOffset());
|
||||
onCoreSeekChanged(Core()->getOffset(), CutterCore::SeekHistoryType::New);
|
||||
emit syncChanged();
|
||||
}
|
||||
|
||||
void CutterSeekable::onCoreSeekChanged(RVA addr)
|
||||
void CutterSeekable::onCoreSeekChanged(RVA addr, CutterCore::SeekHistoryType type)
|
||||
{
|
||||
if (synchronized && widgetOffset != addr) {
|
||||
updateSeek(addr, true);
|
||||
updateSeek(addr, type, true);
|
||||
}
|
||||
}
|
||||
|
||||
void CutterSeekable::updateSeek(RVA addr, bool localOnly)
|
||||
void CutterSeekable::updateSeek(RVA addr, CutterCore::SeekHistoryType type, bool localOnly)
|
||||
{
|
||||
previousOffset = widgetOffset;
|
||||
widgetOffset = addr;
|
||||
@ -32,7 +32,7 @@ void CutterSeekable::updateSeek(RVA addr, bool localOnly)
|
||||
Core()->seek(addr);
|
||||
}
|
||||
|
||||
emit seekableSeekChanged(addr);
|
||||
emit seekableSeekChanged(addr, type);
|
||||
}
|
||||
|
||||
void CutterSeekable::seekPrev()
|
||||
@ -40,7 +40,7 @@ void CutterSeekable::seekPrev()
|
||||
if (synchronized) {
|
||||
Core()->seekPrev();
|
||||
} else {
|
||||
this->seek(previousOffset);
|
||||
this->seek(previousOffset, CutterCore::SeekHistoryType::Undo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,12 @@ public:
|
||||
* signal will be emitted.
|
||||
* In any case, CutterSeekable::seekableSeekChanged is emitted.
|
||||
* @param addr the location to seek at.
|
||||
* @param type the type of seek wrt history (Undo, Redo, or New)
|
||||
*/
|
||||
void seek(RVA addr) { updateSeek(addr, false); }
|
||||
void seek(RVA addr, CutterCore::SeekHistoryType type = CutterCore::SeekHistoryType::New)
|
||||
{
|
||||
updateSeek(addr, type, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief setSynchronization sets
|
||||
@ -67,7 +71,7 @@ private slots:
|
||||
/**
|
||||
* @brief onCoreSeekChanged
|
||||
*/
|
||||
void onCoreSeekChanged(RVA addr);
|
||||
void onCoreSeekChanged(RVA addr, CutterCore::SeekHistoryType type);
|
||||
|
||||
private:
|
||||
/**
|
||||
@ -91,9 +95,9 @@ private:
|
||||
* @brief internal method for changing the seek
|
||||
* @param localOnly whether the seek should be updated globally if synchronized
|
||||
*/
|
||||
void updateSeek(RVA addr, bool localOnly);
|
||||
void updateSeek(RVA addr, CutterCore::SeekHistoryType type, bool localOnly);
|
||||
|
||||
signals:
|
||||
void seekableSeekChanged(RVA addr);
|
||||
void seekableSeekChanged(RVA addr, CutterCore::SeekHistoryType type);
|
||||
void syncChanged();
|
||||
};
|
||||
|
@ -10,6 +10,75 @@ Decompiler::Decompiler(const QString &id, const QString &name, QObject *parent)
|
||||
{
|
||||
}
|
||||
|
||||
static char *jsonToStrdup(const CutterJson &str)
|
||||
{
|
||||
const RzJson *j = str.lowLevelValue();
|
||||
if (!j || j->type != RZ_JSON_STRING) {
|
||||
return NULL;
|
||||
}
|
||||
return rz_str_new(j->str_value);
|
||||
}
|
||||
|
||||
static RzAnnotatedCode *parseJsonCode(CutterJson &json)
|
||||
{
|
||||
char *raw_code = jsonToStrdup(json["code"]);
|
||||
if (!raw_code) {
|
||||
return NULL;
|
||||
}
|
||||
RzAnnotatedCode *code = rz_annotated_code_new(raw_code);
|
||||
if (!code) {
|
||||
return NULL;
|
||||
}
|
||||
for (const auto &jsonAnnotation : json["annotations"]) {
|
||||
RzCodeAnnotation annotation = {};
|
||||
annotation.start = jsonAnnotation["start"].toUt64();
|
||||
annotation.end = jsonAnnotation["end"].toUt64();
|
||||
QString type = jsonAnnotation["type"].toString();
|
||||
if (type == "offset") {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_OFFSET;
|
||||
annotation.offset.offset = jsonAnnotation["offset"].toString().toULongLong();
|
||||
} else if (type == "function_name") {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_FUNCTION_NAME;
|
||||
annotation.reference.name = jsonToStrdup(jsonAnnotation["name"]);
|
||||
annotation.reference.offset = jsonAnnotation["offset"].toString().toULongLong();
|
||||
} else if (type == "global_variable") {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_GLOBAL_VARIABLE;
|
||||
annotation.reference.offset = jsonAnnotation["offset"].toString().toULongLong();
|
||||
} else if (type == "constant_variable") {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_CONSTANT_VARIABLE;
|
||||
annotation.reference.offset = jsonAnnotation["offset"].toString().toULongLong();
|
||||
} else if (type == "local_variable") {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_LOCAL_VARIABLE;
|
||||
annotation.variable.name = jsonToStrdup(jsonAnnotation["name"]);
|
||||
} else if (type == "function_parameter") {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_FUNCTION_PARAMETER;
|
||||
annotation.variable.name = jsonToStrdup(jsonAnnotation["name"]);
|
||||
} else if (type == "syntax_highlight") {
|
||||
annotation.type = RZ_CODE_ANNOTATION_TYPE_SYNTAX_HIGHLIGHT;
|
||||
QString highlightType = jsonAnnotation["syntax_highlight"].toString();
|
||||
if (highlightType == "keyword") {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_KEYWORD;
|
||||
} else if (highlightType == "comment") {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_COMMENT;
|
||||
} else if (highlightType == "datatype") {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_DATATYPE;
|
||||
} else if (highlightType == "function_name") {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_FUNCTION_NAME;
|
||||
} else if (highlightType == "function_parameter") {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_FUNCTION_PARAMETER;
|
||||
} else if (highlightType == "local_variable") {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_LOCAL_VARIABLE;
|
||||
} else if (highlightType == "constant_variable") {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_CONSTANT_VARIABLE;
|
||||
} else if (highlightType == "global_variable") {
|
||||
annotation.syntax_highlight.type = RZ_SYNTAX_HIGHLIGHT_TYPE_GLOBAL_VARIABLE;
|
||||
}
|
||||
}
|
||||
rz_annotated_code_add_annotation(code, &annotation);
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
RzAnnotatedCode *Decompiler::makeWarning(QString warningMessage)
|
||||
{
|
||||
std::string temporary = warningMessage.toStdString();
|
||||
@ -23,7 +92,7 @@ JSDecDecompiler::JSDecDecompiler(QObject *parent) : Decompiler("jsdec", "jsdec",
|
||||
|
||||
bool JSDecDecompiler::isAvailable()
|
||||
{
|
||||
return Core()->cmdList("es").contains("jsdec");
|
||||
return Core()->getConfigVariableSpaces().contains("jsdec");
|
||||
}
|
||||
|
||||
void JSDecDecompiler::decompileAt(RVA addr)
|
||||
@ -31,48 +100,16 @@ void JSDecDecompiler::decompileAt(RVA addr)
|
||||
if (task) {
|
||||
return;
|
||||
}
|
||||
task = new RizinCmdTask("pddj @ " + QString::number(addr));
|
||||
task = new RizinCmdTask("pddA @ " + QString::number(addr));
|
||||
connect(task, &RizinCmdTask::finished, this, [this]() {
|
||||
QJsonObject json = task->getResultJson().object();
|
||||
CutterJson json = task->getResultJson();
|
||||
delete task;
|
||||
task = nullptr;
|
||||
if (json.isEmpty()) {
|
||||
if (!json.size()) {
|
||||
emit finished(Decompiler::makeWarning(tr("Failed to parse JSON from jsdec")));
|
||||
return;
|
||||
}
|
||||
RzAnnotatedCode *code = rz_annotated_code_new(nullptr);
|
||||
QString codeString = "";
|
||||
for (const auto &line : json["log"].toArray()) {
|
||||
if (!line.isString()) {
|
||||
continue;
|
||||
}
|
||||
codeString.append(line.toString() + "\n");
|
||||
}
|
||||
|
||||
auto linesArray = json["lines"].toArray();
|
||||
for (const auto &line : linesArray) {
|
||||
QJsonObject lineObject = line.toObject();
|
||||
if (lineObject.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
RzCodeAnnotation annotationi = {};
|
||||
annotationi.start = codeString.length();
|
||||
codeString.append(lineObject["str"].toString() + "\n");
|
||||
annotationi.end = codeString.length();
|
||||
bool ok;
|
||||
annotationi.type = RZ_CODE_ANNOTATION_TYPE_OFFSET;
|
||||
annotationi.offset.offset = lineObject["offset"].toVariant().toULongLong(&ok);
|
||||
rz_annotated_code_add_annotation(code, &annotationi);
|
||||
}
|
||||
|
||||
for (const auto &line : json["errors"].toArray()) {
|
||||
if (!line.isString()) {
|
||||
continue;
|
||||
}
|
||||
codeString.append(line.toString() + "\n");
|
||||
}
|
||||
std::string tmp = codeString.toStdString();
|
||||
code->code = strdup(tmp.c_str());
|
||||
RzAnnotatedCode *code = parseJsonCode(json);
|
||||
emit finished(code);
|
||||
});
|
||||
task->startTask();
|
||||
|
@ -49,8 +49,7 @@ void DecompilerHighlighter::highlightBlock(const QString &)
|
||||
size_t start = block.position();
|
||||
size_t end = block.position() + block.length();
|
||||
|
||||
std::unique_ptr<RzPVector, decltype(&rz_pvector_free)> annotations(
|
||||
rz_annotated_code_annotations_range(code, start, end), &rz_pvector_free);
|
||||
auto annotations = fromOwned(rz_annotated_code_annotations_range(code, start, end));
|
||||
void **iter;
|
||||
rz_pvector_foreach(annotations.get(), iter)
|
||||
{
|
||||
|
84
src/common/DisassemblyPreview.cpp
Normal file
84
src/common/DisassemblyPreview.cpp
Normal file
@ -0,0 +1,84 @@
|
||||
#include "DisassemblyPreview.h"
|
||||
#include "Configuration.h"
|
||||
#include "widgets/GraphView.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QWidget>
|
||||
#include <QToolTip>
|
||||
#include <QProcessEnvironment>
|
||||
|
||||
DisassemblyTextBlockUserData::DisassemblyTextBlockUserData(const DisassemblyLine &line)
|
||||
: line { line }
|
||||
{
|
||||
}
|
||||
|
||||
DisassemblyTextBlockUserData *getUserData(const QTextBlock &block)
|
||||
{
|
||||
QTextBlockUserData *userData = block.userData();
|
||||
if (!userData) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return static_cast<DisassemblyTextBlockUserData *>(userData);
|
||||
}
|
||||
|
||||
QString DisassemblyPreview::getToolTipStyleSheet()
|
||||
{
|
||||
return QString { "QToolTip { border-width: 1px; max-width: %1px;"
|
||||
"opacity: 230; background-color: %2;"
|
||||
"color: %3; border-color: %3;}" }
|
||||
.arg(400)
|
||||
.arg(Config()->getColor("gui.tooltip.background").name())
|
||||
.arg(Config()->getColor("gui.tooltip.foreground").name());
|
||||
}
|
||||
|
||||
bool DisassemblyPreview::showDisasPreview(QWidget *parent, const QPoint &pointOfEvent,
|
||||
const RVA offsetFrom)
|
||||
{
|
||||
QList<XrefDescription> refs = Core()->getXRefs(offsetFrom, false, false);
|
||||
if (refs.length()) {
|
||||
if (refs.length() > 1) {
|
||||
qWarning() << QObject::tr(
|
||||
"More than one (%1) references here. Weird behaviour expected.")
|
||||
.arg(refs.length());
|
||||
}
|
||||
|
||||
RVA offsetTo = refs.at(0).to; // This is the offset we want to preview
|
||||
/*
|
||||
* Only if the offset we point *to* is different from the one the cursor is currently
|
||||
* on *and* the former is a valid offset, we are allowed to get a preview of offsetTo
|
||||
*/
|
||||
if (offsetTo != offsetFrom && offsetTo != RVA_INVALID) {
|
||||
QStringList disasmPreview = Core()->getDisassemblyPreview(offsetTo, 10);
|
||||
|
||||
// Last check to make sure the returned preview isn't an empty text (QStringList)
|
||||
if (!disasmPreview.isEmpty()) {
|
||||
const QFont &fnt = Config()->getFont();
|
||||
|
||||
QFontMetrics fm { fnt };
|
||||
|
||||
QString tooltip =
|
||||
QString { "<html><div style=\"font-family: %1; font-size: %2pt; "
|
||||
"white-space: nowrap;\"><div style=\"margin-bottom: "
|
||||
"10px;\"><strong>Disassembly Preview</strong>:<br>%3<div>" }
|
||||
.arg(fnt.family())
|
||||
.arg(qMax(8, fnt.pointSize() - 1))
|
||||
.arg(disasmPreview.join("<br>"));
|
||||
|
||||
QToolTip::showText(pointOfEvent, tooltip, parent, QRect {}, 3500);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
RVA DisassemblyPreview::readDisassemblyOffset(QTextCursor tc)
|
||||
{
|
||||
auto userData = getUserData(tc.block());
|
||||
if (!userData) {
|
||||
return RVA_INVALID;
|
||||
}
|
||||
|
||||
return userData->line.offset;
|
||||
}
|
45
src/common/DisassemblyPreview.h
Normal file
45
src/common/DisassemblyPreview.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef DISASSEMBLYPREVIEW_H
|
||||
#define DISASSEMBLYPREVIEW_H
|
||||
|
||||
#include <QTextBlockUserData>
|
||||
|
||||
#include "core/CutterDescriptions.h"
|
||||
|
||||
class QWidget;
|
||||
|
||||
class DisassemblyTextBlockUserData : public QTextBlockUserData
|
||||
{
|
||||
public:
|
||||
DisassemblyLine line;
|
||||
|
||||
explicit DisassemblyTextBlockUserData(const DisassemblyLine &line);
|
||||
};
|
||||
|
||||
DisassemblyTextBlockUserData *getUserData(const QTextBlock &block);
|
||||
|
||||
/**
|
||||
* @brief Namespace to define relevant functions
|
||||
*
|
||||
* @ingroup DisassemblyPreview
|
||||
*/
|
||||
namespace DisassemblyPreview {
|
||||
/*!
|
||||
* @brief Get the QString that defines the stylesheet for tooltip
|
||||
* @return A QString for the stylesheet
|
||||
*/
|
||||
QString getToolTipStyleSheet();
|
||||
|
||||
/*!
|
||||
* @brief Show a QToolTip that previews the disassembly that is pointed to
|
||||
* It works for GraphWidget and DisassemblyWidget
|
||||
* @return True if the tooltip is shown
|
||||
*/
|
||||
bool showDisasPreview(QWidget *parent, const QPoint &pointOfEvent, const RVA offsetFrom);
|
||||
|
||||
/*!
|
||||
* @brief Reads the offset for the cursor position
|
||||
* @return The disassembly offset of the hovered asm text
|
||||
*/
|
||||
RVA readDisassemblyOffset(QTextCursor tc);
|
||||
}
|
||||
#endif
|
@ -9,15 +9,6 @@ Highlighter::Highlighter(QTextDocument *parent) : QSyntaxHighlighter(parent)
|
||||
|
||||
core = Core();
|
||||
|
||||
keywordFormat.setForeground(QColor(65, 131, 215));
|
||||
|
||||
for (const QString &pattern : this->core->opcodes) {
|
||||
rule.pattern.setPattern("\\b" + pattern + "\\b");
|
||||
rule.pattern.setPatternOptions(QRegularExpression::CaseInsensitiveOption);
|
||||
rule.format = keywordFormat;
|
||||
highlightingRules.append(rule);
|
||||
}
|
||||
|
||||
regFormat.setForeground(QColor(236, 100, 75));
|
||||
|
||||
for (const QString &pattern : this->core->regs) {
|
||||
|
@ -77,17 +77,12 @@ bool IOModesController::prepareForWriting()
|
||||
|
||||
bool IOModesController::allChangesComitted()
|
||||
{
|
||||
// Get a list of available write changes
|
||||
QJsonArray changes = Core()->cmdj("wcj").array();
|
||||
|
||||
// Check if there is a change which isn't written to the file
|
||||
for (const QJsonValue &value : changes) {
|
||||
QJsonObject changeObject = value.toObject();
|
||||
if (!changeObject["written"].toBool()) {
|
||||
RzCoreLocked core(Core());
|
||||
for (auto c : CutterPVector<RzIOCache>(&core->io->cache)) {
|
||||
if (!c->written) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -96,7 +91,7 @@ bool IOModesController::askCommitUnsavedChanges()
|
||||
// Check if there are uncommitted changes
|
||||
if (!allChangesComitted()) {
|
||||
QMessageBox::StandardButton ret = QMessageBox::question(
|
||||
NULL, QObject::tr("Uncomitted changes"),
|
||||
NULL, QObject::tr("Uncommitted changes"),
|
||||
QObject::tr("It seems that you have changes or patches that are not committed to "
|
||||
"the file.\n"
|
||||
"Do you want to commit them now?"),
|
||||
@ -105,7 +100,7 @@ bool IOModesController::askCommitUnsavedChanges()
|
||||
if (ret == QMessageBox::Save) {
|
||||
Core()->commitWriteCache();
|
||||
} else if (ret == QMessageBox::Discard) {
|
||||
Core()->cmdRaw("wcr");
|
||||
Core()->resetWriteCache();
|
||||
emit Core()->refreshCodeViews();
|
||||
} else if (ret == QMessageBox::Cancel) {
|
||||
return false;
|
||||
|
@ -40,7 +40,7 @@ struct InitialOptions
|
||||
QString pdbFile;
|
||||
QString script;
|
||||
|
||||
QList<CommandDescription> analCmd = { { "aaa", "Auto analysis" } };
|
||||
QList<CommandDescription> analysisCmd = { { "aaa", "Auto analysis" } };
|
||||
|
||||
QString shellcode;
|
||||
};
|
||||
|
@ -1,123 +1,38 @@
|
||||
#include "JsonModel.h"
|
||||
|
||||
#include <QIODevice>
|
||||
|
||||
JsonModel::JsonModel(QObject *parent) : QAbstractItemModel(parent)
|
||||
QTreeWidgetItem *Cutter::jsonTreeWidgetItem(const QString &key, const CutterJson &json)
|
||||
{
|
||||
mRootItem = new JsonTreeItem;
|
||||
mHeaders.append("key");
|
||||
mHeaders.append("value");
|
||||
}
|
||||
|
||||
JsonModel::~JsonModel()
|
||||
{
|
||||
delete mRootItem;
|
||||
}
|
||||
|
||||
bool JsonModel::load(QIODevice *device)
|
||||
{
|
||||
return loadJson(device->readAll());
|
||||
}
|
||||
|
||||
bool JsonModel::loadJson(const QByteArray &json)
|
||||
{
|
||||
mDocument = QJsonDocument::fromJson(json);
|
||||
|
||||
if (!mDocument.isNull()) {
|
||||
beginResetModel();
|
||||
delete mRootItem;
|
||||
if (mDocument.isArray()) {
|
||||
mRootItem = JsonTreeItem::load(QJsonValue(mDocument.array()));
|
||||
} else {
|
||||
mRootItem = JsonTreeItem::load(QJsonValue(mDocument.object()));
|
||||
QString val;
|
||||
switch (json.type()) {
|
||||
case RZ_JSON_STRING:
|
||||
val = json.toString();
|
||||
break;
|
||||
case RZ_JSON_BOOLEAN:
|
||||
val = json.toBool() ? "true" : "false";
|
||||
break;
|
||||
case RZ_JSON_DOUBLE:
|
||||
val = QString::number(json.lowLevelValue()->num.dbl_value);
|
||||
break;
|
||||
case RZ_JSON_INTEGER:
|
||||
val = QString::number(json.toUt64());
|
||||
break;
|
||||
case RZ_JSON_NULL:
|
||||
val = "null";
|
||||
break;
|
||||
case RZ_JSON_OBJECT:
|
||||
case RZ_JSON_ARRAY:
|
||||
break;
|
||||
}
|
||||
auto r = new QTreeWidgetItem(QStringList({ key, val }));
|
||||
if (json.type() == RZ_JSON_ARRAY) {
|
||||
size_t i = 0;
|
||||
for (const auto &child : json) {
|
||||
r->addChild(jsonTreeWidgetItem(QString::number(i++), child));
|
||||
}
|
||||
} else if (json.type() == RZ_JSON_OBJECT) {
|
||||
for (const auto &child : json) {
|
||||
r->addChild(jsonTreeWidgetItem(child.key(), child));
|
||||
}
|
||||
endResetModel();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
QVariant JsonModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
|
||||
if (!index.isValid())
|
||||
return QVariant();
|
||||
|
||||
JsonTreeItem *item = static_cast<JsonTreeItem *>(index.internalPointer());
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
|
||||
if (index.column() == 0)
|
||||
return QString("%1").arg(item->key());
|
||||
|
||||
if (index.column() == 1)
|
||||
return QString("%1").arg(item->value());
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant JsonModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role != Qt::DisplayRole)
|
||||
return QVariant();
|
||||
|
||||
if (orientation == Qt::Horizontal) {
|
||||
|
||||
return mHeaders.value(section);
|
||||
} else
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QModelIndex JsonModel::index(int row, int column, const QModelIndex &parent) const
|
||||
{
|
||||
if (!hasIndex(row, column, parent))
|
||||
return QModelIndex();
|
||||
|
||||
JsonTreeItem *parentItem;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = mRootItem;
|
||||
else
|
||||
parentItem = static_cast<JsonTreeItem *>(parent.internalPointer());
|
||||
|
||||
JsonTreeItem *childItem = parentItem->child(row);
|
||||
if (childItem)
|
||||
return createIndex(row, column, childItem);
|
||||
else
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
QModelIndex JsonModel::parent(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QModelIndex();
|
||||
|
||||
JsonTreeItem *childItem = static_cast<JsonTreeItem *>(index.internalPointer());
|
||||
JsonTreeItem *parentItem = childItem->parent();
|
||||
|
||||
if (parentItem == mRootItem)
|
||||
return QModelIndex();
|
||||
|
||||
return createIndex(parentItem->row(), 0, parentItem);
|
||||
}
|
||||
|
||||
int JsonModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
JsonTreeItem *parentItem;
|
||||
if (parent.column() > 0)
|
||||
return 0;
|
||||
|
||||
if (!parent.isValid())
|
||||
parentItem = mRootItem;
|
||||
else
|
||||
parentItem = static_cast<JsonTreeItem *>(parent.internalPointer());
|
||||
|
||||
return parentItem->childCount();
|
||||
}
|
||||
|
||||
int JsonModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
Q_UNUSED(parent)
|
||||
return 2;
|
||||
return r;
|
||||
}
|
||||
|
@ -2,37 +2,13 @@
|
||||
#ifndef JSONMODEL_H
|
||||
#define JSONMODEL_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonValue>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QIcon>
|
||||
#include <QTreeWidgetItem>
|
||||
#include "CutterJson.h"
|
||||
|
||||
#include "JsonTreeItem.h"
|
||||
namespace Cutter {
|
||||
|
||||
class JsonTreeItem;
|
||||
QTreeWidgetItem *jsonTreeWidgetItem(const QString &key, const CutterJson &json);
|
||||
|
||||
class JsonModel : public QAbstractItemModel
|
||||
{
|
||||
|
||||
public:
|
||||
explicit JsonModel(QObject *parent = nullptr);
|
||||
bool load(QIODevice *device);
|
||||
bool loadJson(const QByteArray &json);
|
||||
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;
|
||||
QModelIndex index(int row, int column,
|
||||
const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
QModelIndex parent(const QModelIndex &index) const Q_DECL_OVERRIDE;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
~JsonModel();
|
||||
|
||||
private:
|
||||
JsonTreeItem *mRootItem;
|
||||
QJsonDocument mDocument;
|
||||
QStringList mHeaders;
|
||||
};
|
||||
|
||||
#endif // JSONMODEL_H
|
||||
|
@ -1,104 +0,0 @@
|
||||
#include "JsonTreeItem.h"
|
||||
|
||||
JsonTreeItem::JsonTreeItem(JsonTreeItem *parent)
|
||||
{
|
||||
mParent = parent;
|
||||
}
|
||||
|
||||
JsonTreeItem::~JsonTreeItem()
|
||||
{
|
||||
qDeleteAll(mChilds);
|
||||
}
|
||||
|
||||
void JsonTreeItem::appendChild(JsonTreeItem *item)
|
||||
{
|
||||
mChilds.append(item);
|
||||
}
|
||||
|
||||
JsonTreeItem *JsonTreeItem::child(int row)
|
||||
{
|
||||
return mChilds.value(row);
|
||||
}
|
||||
|
||||
JsonTreeItem *JsonTreeItem::parent()
|
||||
{
|
||||
return mParent;
|
||||
}
|
||||
|
||||
int JsonTreeItem::childCount() const
|
||||
{
|
||||
return mChilds.count();
|
||||
}
|
||||
|
||||
int JsonTreeItem::row() const
|
||||
{
|
||||
if (mParent)
|
||||
return mParent->mChilds.indexOf(const_cast<JsonTreeItem *>(this));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void JsonTreeItem::setKey(const QString &key)
|
||||
{
|
||||
mKey = key;
|
||||
}
|
||||
|
||||
void JsonTreeItem::setValue(const QString &value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
void JsonTreeItem::setType(const QJsonValue::Type &type)
|
||||
{
|
||||
mType = type;
|
||||
}
|
||||
|
||||
QString JsonTreeItem::key() const
|
||||
{
|
||||
return mKey;
|
||||
}
|
||||
|
||||
QString JsonTreeItem::value() const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
QJsonValue::Type JsonTreeItem::type() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
JsonTreeItem *JsonTreeItem::load(const QJsonValue &value, JsonTreeItem *parent)
|
||||
{
|
||||
JsonTreeItem *rootItem = new JsonTreeItem(parent);
|
||||
rootItem->setKey("root");
|
||||
|
||||
if (value.isObject()) {
|
||||
|
||||
// Get all QJsonValue childs
|
||||
for (const QString &key : value.toObject().keys()) {
|
||||
QJsonValue v = value.toObject().value(key);
|
||||
JsonTreeItem *child = load(v, rootItem);
|
||||
child->setKey(key);
|
||||
child->setType(v.type());
|
||||
rootItem->appendChild(child);
|
||||
}
|
||||
|
||||
} else if (value.isArray()) {
|
||||
// Get all QJsonValue childs
|
||||
int index = 0;
|
||||
for (const QJsonValue &v : value.toArray()) {
|
||||
|
||||
JsonTreeItem *child = load(v, rootItem);
|
||||
child->setKey(QString::number(index));
|
||||
child->setType(v.type());
|
||||
rootItem->appendChild(child);
|
||||
++index;
|
||||
}
|
||||
} else {
|
||||
rootItem->setValue(value.toVariant().toString());
|
||||
rootItem->setType(value.type());
|
||||
}
|
||||
|
||||
return rootItem;
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
#ifndef JSONTREEITEM_H
|
||||
#define JSONTREEITEM_H
|
||||
|
||||
#include <QAbstractItemModel>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonValue>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QIcon>
|
||||
|
||||
#include "JsonModel.h"
|
||||
|
||||
class JsonTreeItem
|
||||
{
|
||||
public:
|
||||
JsonTreeItem(JsonTreeItem *parent = nullptr);
|
||||
~JsonTreeItem();
|
||||
void appendChild(JsonTreeItem *item);
|
||||
JsonTreeItem *child(int row);
|
||||
JsonTreeItem *parent();
|
||||
int childCount() const;
|
||||
int row() const;
|
||||
void setKey(const QString &key);
|
||||
void setValue(const QString &value);
|
||||
void setType(const QJsonValue::Type &type);
|
||||
QString key() const;
|
||||
QString value() const;
|
||||
QJsonValue::Type type() const;
|
||||
static JsonTreeItem *load(const QJsonValue &value, JsonTreeItem *parent = nullptr);
|
||||
|
||||
private:
|
||||
QString mKey;
|
||||
QString mValue;
|
||||
QJsonValue::Type mType;
|
||||
QList<JsonTreeItem *> mChilds;
|
||||
JsonTreeItem *mParent;
|
||||
};
|
||||
|
||||
#endif // JSONTREEITEM_H
|
@ -13,6 +13,10 @@
|
||||
#ifdef CUTTER_ENABLE_PYTHON_BINDINGS
|
||||
# include <shiboken.h>
|
||||
# include <pyside.h>
|
||||
#ifdef HAVE_PYSIDECLEANUP
|
||||
// This header is introduced in PySide 6
|
||||
# include <pysidecleanup.h>
|
||||
#endif
|
||||
# include <signalmanager.h>
|
||||
#endif
|
||||
|
||||
@ -72,6 +76,7 @@ void PythonManager::initialize()
|
||||
PyImport_AppendInittab("CutterBindings", &PyInit_CutterBindings);
|
||||
#endif
|
||||
Py_Initialize();
|
||||
// This function is deprecated does nothing starting from Python 3.9
|
||||
PyEval_InitThreads();
|
||||
pyThreadStateCounter = 1; // we have the thread now => 1
|
||||
|
||||
@ -159,7 +164,7 @@ void PythonManager::addPythonPath(char *path)
|
||||
if (!append) {
|
||||
return;
|
||||
}
|
||||
PyEval_CallFunction(append, "(s)", path);
|
||||
PyObject_CallFunction(append, "(s)", path);
|
||||
|
||||
saveThread();
|
||||
}
|
||||
|
@ -54,13 +54,15 @@ QString RizinCmdTask::getResult()
|
||||
return QString::fromUtf8(res);
|
||||
}
|
||||
|
||||
QJsonDocument RizinCmdTask::getResultJson()
|
||||
CutterJson RizinCmdTask::getResultJson()
|
||||
{
|
||||
const char *res = rz_core_cmd_task_get_result(task);
|
||||
if (!res) {
|
||||
return QJsonDocument();
|
||||
return CutterJson();
|
||||
}
|
||||
return Core()->parseJson(res, nullptr);
|
||||
char *copy = static_cast<char *>(rz_mem_alloc(strlen(res) + 1));
|
||||
strcpy(copy, res);
|
||||
return Core()->parseJson(copy, nullptr);
|
||||
}
|
||||
|
||||
const char *RizinCmdTask::getResultRaw()
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
explicit RizinCmdTask(const QString &cmd, bool transient = true);
|
||||
|
||||
QString getResult();
|
||||
QJsonDocument getResultJson();
|
||||
CutterJson getResultJson();
|
||||
const char *getResultRaw();
|
||||
};
|
||||
|
||||
|
@ -16,7 +16,10 @@ void RunScriptTask::runTask()
|
||||
{
|
||||
if (!this->fileName.isNull()) {
|
||||
log(tr("Executing script..."));
|
||||
Core()->cmdTask(". " + this->fileName);
|
||||
Core()->functionTask([&](RzCore *core) {
|
||||
rz_core_run_script(core, this->fileName.toUtf8().constData());
|
||||
return nullptr;
|
||||
});
|
||||
if (isInterrupted()) {
|
||||
return;
|
||||
}
|
||||
|
@ -181,21 +181,20 @@ void Cutter::initializeSettings()
|
||||
|
||||
static void removeObsoleteOptionsFromCustomThemes()
|
||||
{
|
||||
const QStringList options = Core()->cmdj("ecj").object().keys()
|
||||
<< ColorThemeWorker::cutterSpecificOptions;
|
||||
for (auto theme : Core()->cmdList("eco*")) {
|
||||
theme = theme.trimmed();
|
||||
if (!ThemeWorker().isCustomTheme(theme)) {
|
||||
const QStringList options = Core()->getThemeKeys() << ColorThemeWorker::cutterSpecificOptions;
|
||||
QStringList themes = Core()->getColorThemes();
|
||||
for (const auto &themeName : themes) {
|
||||
if (!ThemeWorker().isCustomTheme(themeName)) {
|
||||
continue;
|
||||
}
|
||||
QJsonObject updatedTheme;
|
||||
auto sch = ThemeWorker().getTheme(theme).object();
|
||||
for (const auto &key : sch.keys()) {
|
||||
if (options.contains(key)) {
|
||||
updatedTheme.insert(key, sch[key]);
|
||||
ColorThemeWorker::Theme sch = ThemeWorker().getTheme(themeName);
|
||||
ColorThemeWorker::Theme updatedTheme;
|
||||
for (auto it = sch.constBegin(); it != sch.constEnd(); ++it) {
|
||||
if (options.contains(it.key())) {
|
||||
updatedTheme.insert(it.key(), it.value());
|
||||
}
|
||||
}
|
||||
ThemeWorker().save(QJsonDocument(updatedTheme), theme);
|
||||
ThemeWorker().save(updatedTheme, themeName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
# include "Configuration.h"
|
||||
|
||||
# include <KSyntaxHighlighting/theme.h>
|
||||
# include <KSyntaxHighlighting/Theme>
|
||||
|
||||
SyntaxHighlighter::SyntaxHighlighter(QTextDocument *document)
|
||||
: KSyntaxHighlighting::SyntaxHighlighter(document)
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#ifdef CUTTER_ENABLE_KSYNTAXHIGHLIGHTING
|
||||
|
||||
# include <KSyntaxHighlighting/syntaxhighlighter.h>
|
||||
# include <KSyntaxHighlighting/SyntaxHighlighter>
|
||||
|
||||
class SyntaxHighlighter : public KSyntaxHighlighting::SyntaxHighlighter
|
||||
{
|
||||
|
@ -19,7 +19,6 @@
|
||||
* {
|
||||
* TempConfig tempConfig;
|
||||
* tempConfig.set("asm.arch", "x86").set("asm.comments", false);
|
||||
* return Core()->cmdRaw("pd");
|
||||
* // config automatically restored at the end of scope
|
||||
* }
|
||||
* \endcode
|
||||
|
@ -52,29 +52,6 @@ void UpdateWorker::checkCurrentVersion(time_t timeoutMs)
|
||||
pending = true;
|
||||
}
|
||||
|
||||
void UpdateWorker::download(QString filename, QString version)
|
||||
{
|
||||
downloadFile.setFileName(filename);
|
||||
downloadFile.open(QIODevice::WriteOnly);
|
||||
|
||||
QNetworkRequest request;
|
||||
# if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0) && QT_VERSION < QT_VERSION_CHECK(5, 9, 0)
|
||||
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||
# elif QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
||||
request.setAttribute(QNetworkRequest::RedirectPolicyAttribute,
|
||||
QNetworkRequest::RedirectPolicy::NoLessSafeRedirectPolicy);
|
||||
# endif
|
||||
QUrl url(QString("https://github.com/rizinorg/cutter/releases/"
|
||||
"download/v%1/%2")
|
||||
.arg(version)
|
||||
.arg(getRepositoryFileName()));
|
||||
request.setUrl(url);
|
||||
|
||||
downloadReply = nm.get(request);
|
||||
connect(downloadReply, &QNetworkReply::downloadProgress, this, &UpdateWorker::process);
|
||||
connect(downloadReply, &QNetworkReply::finished, this, &UpdateWorker::serveDownloadFinish);
|
||||
}
|
||||
|
||||
void UpdateWorker::showUpdateDialog(bool showDontCheckForUpdatesButton)
|
||||
{
|
||||
QMessageBox mb;
|
||||
@ -82,69 +59,23 @@ void UpdateWorker::showUpdateDialog(bool showDontCheckForUpdatesButton)
|
||||
mb.setText(tr("There is an update available for Cutter.<br/>") + "<b>" + tr("Current version:")
|
||||
+ "</b> " CUTTER_VERSION_FULL "<br/>" + "<b>" + tr("Latest version:") + "</b> "
|
||||
+ latestVersion.toString() + "<br/><br/>"
|
||||
+ tr("For update, please check the link:<br/>")
|
||||
+ tr("To update, please check the link:<br/>")
|
||||
+ QString("<a href=\"https://github.com/rizinorg/cutter/releases/tag/v%1\">"
|
||||
"https://github.com/rizinorg/cutter/releases/tag/v%1</a><br/>")
|
||||
.arg(latestVersion.toString())
|
||||
+ tr("or click \"Download\" to download latest version of Cutter."));
|
||||
.arg(latestVersion.toString()));
|
||||
if (showDontCheckForUpdatesButton) {
|
||||
mb.setStandardButtons(QMessageBox::Save | QMessageBox::Reset | QMessageBox::Ok);
|
||||
mb.button(QMessageBox::Reset)->setText(tr("Don't check for updates"));
|
||||
mb.setStandardButtons(QMessageBox::Reset | QMessageBox::Ok);
|
||||
mb.button(QMessageBox::Reset)->setText(tr("Don't check for updates automatically"));
|
||||
} else {
|
||||
mb.setStandardButtons(QMessageBox::Save | QMessageBox::Ok);
|
||||
mb.setStandardButtons(QMessageBox::Ok);
|
||||
}
|
||||
mb.button(QMessageBox::Save)->setText(tr("Download"));
|
||||
mb.setDefaultButton(QMessageBox::Ok);
|
||||
int ret = mb.exec();
|
||||
if (ret == QMessageBox::Reset) {
|
||||
Config()->setAutoUpdateEnabled(false);
|
||||
} else if (ret == QMessageBox::Save) {
|
||||
QString fullFileName = QFileDialog::getSaveFileName(
|
||||
nullptr, tr("Choose directory for downloading"),
|
||||
QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + QDir::separator()
|
||||
+ getRepositoryFileName(),
|
||||
QString("%1 (*.%1)").arg(getRepositeryExt()));
|
||||
if (!fullFileName.isEmpty()) {
|
||||
QProgressDialog progressDial(tr("Downloading update..."), tr("Cancel"), 0, 100);
|
||||
connect(this, &UpdateWorker::downloadProcess, &progressDial,
|
||||
[&progressDial](size_t curr, size_t total) {
|
||||
progressDial.setValue(100.0f * curr / total);
|
||||
});
|
||||
connect(&progressDial, &QProgressDialog::canceled, this, &UpdateWorker::abortDownload);
|
||||
connect(this, &UpdateWorker::downloadFinished, &progressDial, &QProgressDialog::cancel);
|
||||
connect(this, &UpdateWorker::downloadFinished, this, [](QString filePath) {
|
||||
QMessageBox info(QMessageBox::Information, tr("Download finished!"),
|
||||
tr("Latest version of Cutter was succesfully downloaded!"),
|
||||
QMessageBox::Yes | QMessageBox::Open | QMessageBox::Ok, nullptr);
|
||||
info.button(QMessageBox::Open)->setText(tr("Open file"));
|
||||
info.button(QMessageBox::Yes)->setText(tr("Open download folder"));
|
||||
int r = info.exec();
|
||||
if (r == QMessageBox::Open) {
|
||||
QDesktopServices::openUrl(filePath);
|
||||
} else if (r == QMessageBox::Yes) {
|
||||
auto path = filePath.split('/');
|
||||
path.removeLast();
|
||||
QDesktopServices::openUrl(path.join('/'));
|
||||
}
|
||||
});
|
||||
download(fullFileName, latestVersion.toString());
|
||||
// Calling show() before exec() is only way make dialog non-modal
|
||||
// it seems weird, but it works
|
||||
progressDial.show();
|
||||
progressDial.exec();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateWorker::abortDownload()
|
||||
{
|
||||
disconnect(downloadReply, &QNetworkReply::finished, this, &UpdateWorker::serveDownloadFinish);
|
||||
disconnect(downloadReply, &QNetworkReply::downloadProgress, this, &UpdateWorker::process);
|
||||
downloadReply->close();
|
||||
downloadReply->deleteLater();
|
||||
downloadFile.remove();
|
||||
}
|
||||
|
||||
void UpdateWorker::serveVersionCheckReply()
|
||||
{
|
||||
pending = false;
|
||||
@ -168,51 +99,6 @@ void UpdateWorker::serveVersionCheckReply()
|
||||
emit checkComplete(versionReply, errStr);
|
||||
}
|
||||
|
||||
void UpdateWorker::serveDownloadFinish()
|
||||
{
|
||||
downloadReply->close();
|
||||
downloadReply->deleteLater();
|
||||
if (downloadReply->error()) {
|
||||
emit downloadError(downloadReply->errorString());
|
||||
} else {
|
||||
emit downloadFinished(downloadFile.fileName());
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateWorker::process(size_t bytesReceived, size_t bytesTotal)
|
||||
{
|
||||
downloadFile.write(downloadReply->readAll());
|
||||
emit downloadProcess(bytesReceived, bytesTotal);
|
||||
}
|
||||
|
||||
QString UpdateWorker::getRepositeryExt() const
|
||||
{
|
||||
# ifdef Q_OS_LINUX
|
||||
return "AppImage";
|
||||
# elif defined(Q_OS_WIN64) || defined(Q_OS_WIN32)
|
||||
return "zip";
|
||||
# elif defined(Q_OS_MACOS)
|
||||
return "dmg";
|
||||
# endif
|
||||
}
|
||||
|
||||
QString UpdateWorker::getRepositoryFileName() const
|
||||
{
|
||||
QString downloadFileName;
|
||||
# ifdef Q_OS_LINUX
|
||||
downloadFileName = "Cutter-v%1-x%2.Linux.AppImage";
|
||||
# elif defined(Q_OS_WIN64) || defined(Q_OS_WIN32)
|
||||
downloadFileName = "Cutter-v%1-x%2.Windows.zip";
|
||||
# elif defined(Q_OS_MACOS)
|
||||
downloadFileName = "Cutter-v%1-x%2.macOS.dmg";
|
||||
# endif
|
||||
downloadFileName =
|
||||
downloadFileName.arg(latestVersion.toString())
|
||||
.arg(QSysInfo::buildAbi().split('-').at(2).contains("64") ? "64" : "32");
|
||||
|
||||
return downloadFileName;
|
||||
}
|
||||
|
||||
QVersionNumber UpdateWorker::currentVersionNumber()
|
||||
{
|
||||
return QVersionNumber(CUTTER_VERSION_MAJOR, CUTTER_VERSION_MINOR, CUTTER_VERSION_PATCH);
|
||||
|
@ -23,8 +23,7 @@ class QNetworkReply;
|
||||
|
||||
/**
|
||||
* @class UpdateWorker
|
||||
* @brief The UpdateWorker class is a class providing API to check for current Cutter version
|
||||
* and download specific version of one.
|
||||
* @brief The UpdateWorker class is a class providing API to check for current Cutter version.
|
||||
*/
|
||||
|
||||
class UpdateWorker : public QObject
|
||||
@ -47,23 +46,12 @@ public:
|
||||
|
||||
void checkCurrentVersion(time_t timeoutMs);
|
||||
|
||||
/**
|
||||
* @fn void UpdateWorker::download(QDir downloadPath, QString version)
|
||||
*
|
||||
* @brief Downloads provided @a version of Cutter into @a downloadDir.
|
||||
*
|
||||
* @sa downloadProcess(size_t bytesReceived, size_t bytesTotal)
|
||||
*/
|
||||
void download(QString filename, QString version);
|
||||
|
||||
/**
|
||||
* @fn void UpdateWorker::showUpdateDialog()
|
||||
*
|
||||
* Shows dialog that allows user to either download latest version of Cutter from website
|
||||
* or download it by clicking on a button. This dialog also has "Don't check for updates"
|
||||
* button which disables on-start update checks if @a showDontCheckForUpdatesButton is true.
|
||||
*
|
||||
* @sa downloadProcess(size_t bytesReceived, size_t bytesTotal)
|
||||
* Shows dialog that allows user to download latest version of Cutter from website.
|
||||
* This dialog also has "Don't check for updates" button which disables on-start update
|
||||
* checks if @a showDontCheckForUpdatesButton is true.
|
||||
*/
|
||||
void showUpdateDialog(bool showDontCheckForUpdatesButton);
|
||||
|
||||
@ -73,18 +61,6 @@ public:
|
||||
*/
|
||||
static QVersionNumber currentVersionNumber();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @fn void UpdateWorker::abortDownload()
|
||||
*
|
||||
* @brief Stops current process of downloading.
|
||||
*
|
||||
* @note UpdateWorker::downloadFinished(QString filename) is not send after this function.
|
||||
*
|
||||
* @sa download(QDir downloadDir, QString version)
|
||||
*/
|
||||
void abortDownload();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @fn UpdateWorker::checkComplete(const QString& verson, const QString& errorMsg)
|
||||
@ -95,46 +71,14 @@ signals:
|
||||
*/
|
||||
void checkComplete(const QVersionNumber &currVerson, const QString &errorMsg);
|
||||
|
||||
/**
|
||||
* @fn UpdateWorker::downloadProcess(size_t bytesReceived, size_t bytesTotal)
|
||||
*
|
||||
* The signal is emitted each time when some amount of bytes was downloaded.
|
||||
* May be used as indicator of download progress.
|
||||
*/
|
||||
void downloadProcess(size_t bytesReceived, size_t bytesTotal);
|
||||
|
||||
/**
|
||||
* @fn UpdateWorker::downloadFinished(QString filename)
|
||||
*
|
||||
* @brief The signal is emitted as soon as downloading completes.
|
||||
*/
|
||||
void downloadFinished(QString filename);
|
||||
|
||||
/**
|
||||
* @fn UpdateWorker::downloadError(QString errorStr)
|
||||
*
|
||||
* @brief The signal is emitted when error occures during download.
|
||||
*/
|
||||
void downloadError(QString errorStr);
|
||||
|
||||
private slots:
|
||||
void serveVersionCheckReply();
|
||||
|
||||
void serveDownloadFinish();
|
||||
|
||||
void process(size_t bytesReceived, size_t bytesTotal);
|
||||
|
||||
private:
|
||||
QString getRepositeryExt() const;
|
||||
QString getRepositoryFileName() const;
|
||||
|
||||
private:
|
||||
QNetworkAccessManager nm;
|
||||
QVersionNumber latestVersion;
|
||||
QTimer t;
|
||||
bool pending;
|
||||
QFile downloadFile;
|
||||
QNetworkReply *downloadReply;
|
||||
QNetworkReply *checkReply;
|
||||
};
|
||||
|
||||
|
109
src/core/Basefind.cpp
Normal file
109
src/core/Basefind.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
#include "Basefind.h"
|
||||
|
||||
bool Basefind::threadCallback(const RzBaseFindThreadInfo *info, void *user)
|
||||
{
|
||||
auto th = reinterpret_cast<Basefind *>(user);
|
||||
return th->updateProgress(info);
|
||||
}
|
||||
|
||||
Basefind::Basefind(CutterCore *core)
|
||||
: core(core),
|
||||
scores(nullptr),
|
||||
continue_run(true)
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
,
|
||||
mutex(QMutex::Recursive)
|
||||
#endif
|
||||
{
|
||||
memset(&options, 0, sizeof(RzBaseFindOpt));
|
||||
}
|
||||
|
||||
Basefind::~Basefind()
|
||||
{
|
||||
cancel();
|
||||
wait();
|
||||
rz_list_free(scores);
|
||||
}
|
||||
|
||||
bool Basefind::setOptions(const RzBaseFindOpt *opts)
|
||||
{
|
||||
mutex.lock();
|
||||
options.max_threads = opts->max_threads;
|
||||
options.pointer_size = opts->pointer_size;
|
||||
options.start_address = opts->start_address;
|
||||
options.end_address = opts->end_address;
|
||||
options.alignment = opts->alignment;
|
||||
options.min_score = opts->min_score;
|
||||
options.min_string_len = opts->min_string_len;
|
||||
mutex.unlock();
|
||||
|
||||
if (options.start_address >= options.end_address) {
|
||||
qWarning() << "Start address is >= end address";
|
||||
return false;
|
||||
} else if (options.alignment < RZ_BASEFIND_BASE_ALIGNMENT) {
|
||||
qWarning() << "Alignment must be at least "
|
||||
<< QString::asprintf("0x%x", RZ_BASEFIND_BASE_ALIGNMENT);
|
||||
return false;
|
||||
} else if (options.min_score < 1) {
|
||||
qWarning() << "Min score must be at least 1";
|
||||
return false;
|
||||
} else if (options.min_string_len < 1) {
|
||||
qWarning() << "Min string length must be at least 1";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Basefind::run()
|
||||
{
|
||||
qRegisterMetaType<BasefindCoreStatusDescription>();
|
||||
|
||||
mutex.lock();
|
||||
rz_list_free(scores);
|
||||
scores = nullptr;
|
||||
continue_run = true;
|
||||
mutex.unlock();
|
||||
|
||||
core->coreMutex.lock();
|
||||
options.callback = threadCallback;
|
||||
options.user = this;
|
||||
scores = rz_basefind(core->core_, &options);
|
||||
core->coreMutex.unlock();
|
||||
|
||||
emit complete();
|
||||
}
|
||||
|
||||
void Basefind::cancel()
|
||||
{
|
||||
mutex.lock();
|
||||
continue_run = false;
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
QList<BasefindResultDescription> Basefind::results()
|
||||
{
|
||||
QList<BasefindResultDescription> pairs;
|
||||
RzListIter *it;
|
||||
RzBaseFindScore *pair;
|
||||
CutterRzListForeach (scores, it, RzBaseFindScore, pair) {
|
||||
BasefindResultDescription desc;
|
||||
desc.candidate = pair->candidate;
|
||||
desc.score = pair->score;
|
||||
pairs.push_back(desc);
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
|
||||
bool Basefind::updateProgress(const RzBaseFindThreadInfo *info)
|
||||
{
|
||||
mutex.lock();
|
||||
|
||||
BasefindCoreStatusDescription status;
|
||||
status.index = info->thread_idx;
|
||||
status.percentage = info->percentage;
|
||||
|
||||
emit progress(status);
|
||||
bool ret = continue_run;
|
||||
mutex.unlock();
|
||||
return ret;
|
||||
}
|
47
src/core/Basefind.h
Normal file
47
src/core/Basefind.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef CUTTER_BASEFIND_CORE_H
|
||||
#define CUTTER_BASEFIND_CORE_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
|
||||
#include "Cutter.h"
|
||||
#include "CutterDescriptions.h"
|
||||
#include <rz_basefind.h>
|
||||
|
||||
class CutterCore;
|
||||
|
||||
class Basefind : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Basefind(CutterCore *core);
|
||||
virtual ~Basefind();
|
||||
|
||||
void run();
|
||||
bool setOptions(const RzBaseFindOpt *opts);
|
||||
QList<BasefindResultDescription> results();
|
||||
|
||||
public slots:
|
||||
void cancel();
|
||||
|
||||
signals:
|
||||
void progress(BasefindCoreStatusDescription status);
|
||||
void complete();
|
||||
|
||||
private:
|
||||
CutterCore *const core;
|
||||
RzList *scores;
|
||||
bool continue_run;
|
||||
RzBaseFindOpt options;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
|
||||
QMutex mutex;
|
||||
#else
|
||||
QRecursiveMutex mutex;
|
||||
#endif
|
||||
|
||||
bool updateProgress(const RzBaseFindThreadInfo *info);
|
||||
static bool threadCallback(const RzBaseFindThreadInfo *info, void *user);
|
||||
};
|
||||
|
||||
#endif // CUTTER_BASEFIND_CORE_H
|
2751
src/core/Cutter.cpp
2751
src/core/Cutter.cpp
File diff suppressed because it is too large
Load Diff
@ -3,18 +3,22 @@
|
||||
|
||||
#include "core/CutterCommon.h"
|
||||
#include "core/CutterDescriptions.h"
|
||||
#include "core/CutterJson.h"
|
||||
#include "core/Basefind.h"
|
||||
#include "common/BasicInstructionHighlighter.h"
|
||||
|
||||
#include <QMap>
|
||||
#include <QMenu>
|
||||
#include <QDebug>
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QStringList>
|
||||
#include <QMessageBox>
|
||||
#include <QJsonDocument>
|
||||
#include <QErrorMessage>
|
||||
#include <QMutex>
|
||||
#include <QDir>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
class AsyncTaskManager;
|
||||
class BasicInstructionHighlighter;
|
||||
@ -22,23 +26,51 @@ class CutterCore;
|
||||
class Decompiler;
|
||||
class RizinTask;
|
||||
class RizinCmdTask;
|
||||
class RizinFunctionTask;
|
||||
class RizinTaskDialog;
|
||||
|
||||
#include "common/BasicBlockHighlighter.h"
|
||||
#include "common/Helpers.h"
|
||||
|
||||
#include <rz_project.h>
|
||||
#include <memory>
|
||||
|
||||
#define Core() (CutterCore::instance())
|
||||
|
||||
class RzCoreLocked;
|
||||
|
||||
struct CUTTER_EXPORT AddrRefs
|
||||
{
|
||||
RVA addr;
|
||||
QString mapname;
|
||||
QString section;
|
||||
QString reg;
|
||||
QString fcn;
|
||||
QString type;
|
||||
QString asm_op;
|
||||
QString perms;
|
||||
ut64 value;
|
||||
bool has_value;
|
||||
QString string;
|
||||
QSharedPointer<AddrRefs> ref;
|
||||
};
|
||||
|
||||
struct CUTTER_EXPORT RegisterRef
|
||||
{
|
||||
ut64 value;
|
||||
AddrRefs ref;
|
||||
QString name;
|
||||
};
|
||||
|
||||
using PRzAnalysisBytes = std::unique_ptr<RzAnalysisBytes, decltype(rz_analysis_bytes_free) *>;
|
||||
|
||||
class CUTTER_EXPORT CutterCore : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
friend class RzCoreLocked;
|
||||
friend class RizinTask;
|
||||
friend class Basefind;
|
||||
|
||||
public:
|
||||
explicit CutterCore(QObject *parent = nullptr);
|
||||
@ -55,6 +87,10 @@ public:
|
||||
RVA getOffset() const { return core_->offset; }
|
||||
|
||||
/* Core functions (commands) */
|
||||
/* Almost the same as core_cmd_raw,
|
||||
* only executes std::function<bool(RzCore *)> instead of char* */
|
||||
QString getFunctionExecOut(const std::function<bool(RzCore *)> &fcn,
|
||||
const RVA addr = RVA_INVALID);
|
||||
static QString sanitizeStringForCommand(QString s);
|
||||
/**
|
||||
* @brief send a command to Rizin
|
||||
@ -64,21 +100,14 @@ public:
|
||||
*/
|
||||
QString cmd(const char *str);
|
||||
QString cmd(const QString &str) { return cmd(str.toUtf8().constData()); }
|
||||
|
||||
/**
|
||||
* @brief send a command to Rizin asynchronously
|
||||
* @param str the command you want to execute
|
||||
* @param task a shared pointer that will be returned with the Rizin command task
|
||||
* @note connect to the &RizinTask::finished signal to add your own logic once
|
||||
* the command is finished. Use task->getResult()/getResultJson() for the
|
||||
* return value.
|
||||
* Once you have setup connections you can start the task with task->startTask()
|
||||
* If you want to seek to an address, you should use CutterCore::seek.
|
||||
* @brief send a task to Rizin
|
||||
* @param fcn the task you want to execute
|
||||
* @return execute successful?
|
||||
*/
|
||||
bool asyncCmd(const char *str, QSharedPointer<RizinCmdTask> &task);
|
||||
bool asyncCmd(const QString &str, QSharedPointer<RizinCmdTask> &task)
|
||||
{
|
||||
return asyncCmd(str.toUtf8().constData(), task);
|
||||
}
|
||||
bool asyncTask(std::function<void *(RzCore *)> fcn, QSharedPointer<RizinTask> &task);
|
||||
void functionTask(std::function<void *(RzCore *)> fcn);
|
||||
|
||||
/**
|
||||
* @brief Execute a Rizin command \a cmd. By nature, the API
|
||||
@ -115,43 +144,47 @@ public:
|
||||
return cmdRawAt(str.toUtf8().constData(), address);
|
||||
}
|
||||
|
||||
QJsonDocument cmdj(const char *str);
|
||||
QJsonDocument cmdj(const QString &str) { return cmdj(str.toUtf8().constData()); }
|
||||
QJsonDocument cmdjAt(const char *str, RVA address);
|
||||
QStringList cmdList(const char *str)
|
||||
class SeekReturn
|
||||
{
|
||||
return cmd(str).split(QLatin1Char('\n'), CUTTER_QT_SKIP_EMPTY_PARTS);
|
||||
RVA returnAddress;
|
||||
bool empty = true;
|
||||
|
||||
public:
|
||||
SeekReturn(RVA returnAddress) : returnAddress(returnAddress), empty(false) {}
|
||||
~SeekReturn()
|
||||
{
|
||||
if (!empty) {
|
||||
Core()->seekSilent(returnAddress);
|
||||
}
|
||||
}
|
||||
SeekReturn(SeekReturn &&from)
|
||||
{
|
||||
if (this != &from) {
|
||||
returnAddress = from.returnAddress;
|
||||
empty = from.empty;
|
||||
from.empty = true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
SeekReturn seekTemp(RVA address)
|
||||
{
|
||||
SeekReturn returner(getOffset());
|
||||
seekSilent(address);
|
||||
return returner;
|
||||
}
|
||||
QStringList cmdList(const QString &str) { return cmdList(str.toUtf8().constData()); }
|
||||
|
||||
enum class SeekHistoryType { New, Undo, Redo };
|
||||
|
||||
CutterJson cmdj(const char *str);
|
||||
CutterJson cmdj(const QString &str) { return cmdj(str.toUtf8().constData()); }
|
||||
QString cmdTask(const QString &str);
|
||||
QJsonDocument cmdjTask(const QString &str);
|
||||
/**
|
||||
* @brief send a command to Rizin and check for ESIL errors
|
||||
* @param command the command you want to execute
|
||||
* @note If you want to seek to an address, you should use CutterCore::seek.
|
||||
*/
|
||||
void cmdEsil(const char *command);
|
||||
void cmdEsil(const QString &command) { cmdEsil(command.toUtf8().constData()); }
|
||||
/**
|
||||
* @brief send a command to Rizin and check for ESIL errors
|
||||
* @param command the command you want to execute
|
||||
* @param task a shared pointer that will be returned with the Rizin command task
|
||||
* @note connect to the &RizinTask::finished signal to add your own logic once
|
||||
* the command is finished. Use task->getResult()/getResultJson() for the
|
||||
* return value.
|
||||
* Once you have setup connections you can start the task with task->startTask()
|
||||
* If you want to seek to an address, you should use CutterCore::seek.
|
||||
*/
|
||||
bool asyncCmdEsil(const char *command, QSharedPointer<RizinCmdTask> &task);
|
||||
bool asyncCmdEsil(const QString &command, QSharedPointer<RizinCmdTask> &task)
|
||||
{
|
||||
return asyncCmdEsil(command.toUtf8().constData(), task);
|
||||
}
|
||||
QString getRizinVersionReadable();
|
||||
|
||||
QString getRizinVersionReadable(const char *program = nullptr);
|
||||
QString getVersionInformation();
|
||||
|
||||
QJsonDocument parseJson(const char *res, const char *cmd = nullptr);
|
||||
QJsonDocument parseJson(const char *res, const QString &cmd = QString())
|
||||
CutterJson parseJson(char *res, const char *cmd = nullptr);
|
||||
CutterJson parseJson(char *res, const QString &cmd = QString())
|
||||
{
|
||||
return parseJson(res, cmd.isNull() ? nullptr : cmd.toLocal8Bit().constData());
|
||||
}
|
||||
@ -187,10 +220,9 @@ public:
|
||||
RVA getFunctionStart(RVA addr);
|
||||
RVA getFunctionEnd(RVA addr);
|
||||
RVA getLastFunctionInstruction(RVA addr);
|
||||
QString cmdFunctionAt(QString addr);
|
||||
QString cmdFunctionAt(RVA addr);
|
||||
QString createFunctionAt(RVA addr);
|
||||
QString createFunctionAt(RVA addr, QString name);
|
||||
QString flagAt(RVA addr);
|
||||
void createFunctionAt(RVA addr);
|
||||
void createFunctionAt(RVA addr, QString name);
|
||||
QStringList getDisassemblyPreview(RVA address, int num_of_lines);
|
||||
|
||||
/* Flags */
|
||||
@ -208,9 +240,10 @@ public:
|
||||
void triggerFlagsChanged();
|
||||
|
||||
/* Edition functions */
|
||||
PRzAnalysisBytes getRzAnalysisBytesSingle(RVA addr);
|
||||
QString getInstructionBytes(RVA addr);
|
||||
QString getInstructionOpcode(RVA addr);
|
||||
void editInstruction(RVA addr, const QString &inst);
|
||||
void editInstruction(RVA addr, const QString &inst, bool fillWithNops = false);
|
||||
void nopInstruction(RVA addr);
|
||||
void jmpReverse(RVA addr);
|
||||
void editBytes(RVA addr, const QString &inst);
|
||||
@ -233,6 +266,13 @@ public:
|
||||
* \param addr The address of the array where the string will be applied
|
||||
*/
|
||||
void removeString(RVA addr);
|
||||
/**
|
||||
* @brief Gets string at address
|
||||
* That function correspond the 'Cs.' command
|
||||
* \param addr The address of the string
|
||||
* @return string at requested address
|
||||
*/
|
||||
QString getMetaString(RVA addr);
|
||||
/**
|
||||
* @brief Gets string at address
|
||||
* That function calls the 'ps' command
|
||||
@ -240,6 +280,7 @@ public:
|
||||
* @return string at requested address
|
||||
*/
|
||||
QString getString(RVA addr);
|
||||
QString getString(RVA addr, uint64_t len, RzStrEnc encoding, bool escape_nl = false);
|
||||
void setToData(RVA addr, int size, int repeat = 1);
|
||||
int sizeofDataMeta(RVA addr);
|
||||
|
||||
@ -260,17 +301,18 @@ public:
|
||||
void applyStructureOffset(const QString &structureOffset, RVA offset = RVA_INVALID);
|
||||
|
||||
/* Classes */
|
||||
QList<QString> getAllAnalClasses(bool sorted);
|
||||
QList<AnalMethodDescription> getAnalClassMethods(const QString &cls);
|
||||
QList<AnalBaseClassDescription> getAnalClassBaseClasses(const QString &cls);
|
||||
QList<AnalVTableDescription> getAnalClassVTables(const QString &cls);
|
||||
QList<QString> getAllAnalysisClasses(bool sorted);
|
||||
QList<AnalysisMethodDescription> getAnalysisClassMethods(const QString &cls);
|
||||
QList<AnalysisBaseClassDescription> getAnalysisClassBaseClasses(const QString &cls);
|
||||
QList<AnalysisVTableDescription> getAnalysisClassVTables(const QString &cls);
|
||||
void createNewClass(const QString &cls);
|
||||
void renameClass(const QString &oldName, const QString &newName);
|
||||
void deleteClass(const QString &cls);
|
||||
bool getAnalMethod(const QString &cls, const QString &meth, AnalMethodDescription *desc);
|
||||
void renameAnalMethod(const QString &className, const QString &oldMethodName,
|
||||
const QString &newMethodName);
|
||||
void setAnalMethod(const QString &cls, const AnalMethodDescription &meth);
|
||||
bool getAnalysisMethod(const QString &cls, const QString &meth,
|
||||
AnalysisMethodDescription *desc);
|
||||
void renameAnalysisMethod(const QString &className, const QString &oldMethodName,
|
||||
const QString &newMethodName);
|
||||
void setAnalysisMethod(const QString &cls, const AnalysisMethodDescription &meth);
|
||||
|
||||
/* File related methods */
|
||||
bool loadFile(QString path, ut64 baddr = 0LL, ut64 mapaddr = 0LL, int perms = RZ_PERM_R,
|
||||
@ -278,7 +320,6 @@ public:
|
||||
bool tryFile(QString path, bool rw);
|
||||
bool mapFile(QString path, RVA mapaddr);
|
||||
void loadScript(const QString &scriptname);
|
||||
QJsonArray getOpenedFiles();
|
||||
|
||||
/* Seek functions */
|
||||
void seek(QString thing);
|
||||
@ -287,7 +328,7 @@ public:
|
||||
void seekSilent(QString thing) { seekSilent(math(thing)); }
|
||||
void seekPrev();
|
||||
void seekNext();
|
||||
void updateSeek();
|
||||
void updateSeek(SeekHistoryType type = SeekHistoryType::New);
|
||||
/**
|
||||
* @brief Raise a memory widget showing current offset, prefer last active
|
||||
* memory widget.
|
||||
@ -307,6 +348,10 @@ public:
|
||||
RVA prevOpAddr(RVA startAddr, int count);
|
||||
RVA nextOpAddr(RVA startAddr, int count);
|
||||
|
||||
/* SigDB / Flirt functions */
|
||||
void applySignature(const QString &filepath);
|
||||
void createSignature(const QString &filepath);
|
||||
|
||||
/* Math functions */
|
||||
ut64 math(const QString &expr);
|
||||
ut64 num(const QString &expr);
|
||||
@ -332,7 +377,12 @@ public:
|
||||
QString getConfig(const char *k);
|
||||
QString getConfig(const QString &k) { return getConfig(k.toUtf8().constData()); }
|
||||
QString getConfigDescription(const char *k);
|
||||
QList<QString> getColorThemes();
|
||||
QStringList getConfigOptions(const char *k);
|
||||
QStringList getColorThemes();
|
||||
QHash<QString, QColor> getTheme();
|
||||
QStringList getThemeKeys();
|
||||
bool setColor(const QString &key, const QString &color);
|
||||
QStringList getConfigVariableSpaces(const QString &key = "");
|
||||
|
||||
/* Assembly\Hexdump related methods */
|
||||
QByteArray assemble(const QString &code);
|
||||
@ -356,8 +406,6 @@ public:
|
||||
bool sdbSet(QString path, QString key, QString val);
|
||||
|
||||
/* Debug */
|
||||
QJsonDocument getRegistersInfo();
|
||||
QJsonDocument getRegisterValues();
|
||||
QString getRegisterName(QString registerRole);
|
||||
RVA getProgramCounterValue();
|
||||
void setRegister(QString regName, QString regValue);
|
||||
@ -371,32 +419,25 @@ public:
|
||||
* @param size number of bytes to scan
|
||||
* @param depth telescoping depth
|
||||
*/
|
||||
QList<QJsonObject> getStack(int size = 0x100, int depth = 6);
|
||||
QList<AddrRefs> getStack(int size = 0x100, int depth = 6);
|
||||
/**
|
||||
* @brief Recursively dereferences pointers starting at the specified address
|
||||
* up to a given depth
|
||||
* @param addr telescoping addr
|
||||
* @param depth telescoping depth
|
||||
*/
|
||||
QJsonObject getAddrRefs(RVA addr, int depth);
|
||||
AddrRefs getAddrRefs(RVA addr, int depth);
|
||||
/**
|
||||
* @brief return a RefDescription with a formatted ref string and configured colors
|
||||
* @param ref the "ref" JSON node from getAddrRefs
|
||||
*/
|
||||
RefDescription formatRefDesc(QJsonObject ref);
|
||||
RefDescription formatRefDesc(const QSharedPointer<AddrRefs> &ref);
|
||||
/**
|
||||
* @brief Get a list of a given process's threads
|
||||
* @param pid The pid of the process, -1 for the currently debugged process
|
||||
* @return JSON object result of dptj
|
||||
* @return List of ProcessDescription
|
||||
*/
|
||||
QJsonDocument getProcessThreads(int pid);
|
||||
/**
|
||||
* @brief Get a list of a given process's child processes
|
||||
* @param pid The pid of the process, -1 for the currently debugged process
|
||||
* @return JSON object result of dptj
|
||||
*/
|
||||
QJsonDocument getChildProcesses(int pid);
|
||||
QJsonDocument getBacktrace();
|
||||
QList<ProcessDescription> getProcessThreads(int pid);
|
||||
/**
|
||||
* @brief Get a list of heap chunks
|
||||
* Uses RZ_API rz_heap_chunks_list to get vector of chunks
|
||||
@ -419,7 +460,20 @@ public:
|
||||
* @return RzHeapChunkSimple struct pointer for the heap chunk
|
||||
*/
|
||||
RzHeapChunkSimple *getHeapChunk(ut64 addr);
|
||||
/**
|
||||
* @brief Get heap bins of an arena with given base address
|
||||
* (including large, small, fast, unsorted, tcache)
|
||||
* @param arena_addr Base address of the arena
|
||||
* @return QVector of non empty RzHeapBin pointers
|
||||
*/
|
||||
QVector<RzHeapBin *> getHeapBins(ut64 arena_addr);
|
||||
/**
|
||||
* @brief Write the given chunk header to memory
|
||||
* @param chunkSimple RzHeapChunkSimple pointer of the chunk to be written
|
||||
* @return true if the write succeeded else false
|
||||
*/
|
||||
bool writeHeapChunk(RzHeapChunkSimple *chunkSimple);
|
||||
int getArchBits();
|
||||
void startDebug();
|
||||
void startEmulation();
|
||||
/**
|
||||
@ -436,7 +490,7 @@ public:
|
||||
void continueBackDebug();
|
||||
void continueUntilCall();
|
||||
void continueUntilSyscall();
|
||||
void continueUntilDebug(QString offset);
|
||||
void continueUntilDebug(ut64 offset);
|
||||
void stepDebug();
|
||||
void stepOverDebug();
|
||||
void stepOutDebug();
|
||||
@ -499,15 +553,14 @@ public:
|
||||
bool registerDecompiler(Decompiler *decompiler);
|
||||
|
||||
RVA getOffsetJump(RVA addr);
|
||||
QJsonDocument getFileInfo();
|
||||
QJsonDocument getSignatureInfo();
|
||||
QJsonDocument getFileVersionInfo();
|
||||
QStringList getStats();
|
||||
CutterJson getSignatureInfo();
|
||||
bool existsFileInfo();
|
||||
void setGraphEmpty(bool empty);
|
||||
bool isGraphEmpty();
|
||||
|
||||
void getOpcodes();
|
||||
QList<QString> opcodes;
|
||||
bool rebaseBin(RVA base_address);
|
||||
|
||||
void getRegs();
|
||||
QList<QString> regs;
|
||||
void setSettings();
|
||||
|
||||
@ -519,10 +572,10 @@ public:
|
||||
|
||||
/* Plugins */
|
||||
QStringList getAsmPluginNames();
|
||||
QStringList getAnalPluginNames();
|
||||
QStringList getAnalysisPluginNames();
|
||||
|
||||
/* Widgets */
|
||||
QList<RzBinPluginDescription> getRBinPluginDescriptions(const QString &type = QString());
|
||||
QList<RzBinPluginDescription> getBinPluginDescriptions(bool bin = true, bool xtr = true);
|
||||
QList<RzIOPluginDescription> getRIOPluginDescriptions();
|
||||
QList<RzCorePluginDescription> getRCorePluginDescriptions();
|
||||
QList<RzAsmPluginDescription> getRAsmPluginDescriptions();
|
||||
@ -531,7 +584,7 @@ public:
|
||||
QList<ExportDescription> getAllExports();
|
||||
QList<SymbolDescription> getAllSymbols();
|
||||
QList<HeaderDescription> getAllHeaders();
|
||||
QList<ZignatureDescription> getAllZignatures();
|
||||
QList<FlirtDescription> getSignaturesDB();
|
||||
QList<CommentDescription> getAllComments(const QString &filterType);
|
||||
QList<RelocDescription> getAllRelocs();
|
||||
QList<StringDescription> getAllStrings();
|
||||
@ -577,23 +630,10 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Fetching the C representation of a given Type
|
||||
* @param name - the name or the type of the given Type / Struct
|
||||
* @param category - the category of the given Type (Struct, Union, Enum, ...)
|
||||
* @param name - the name or the type of the given Type
|
||||
* @return The type decleration as C output
|
||||
*/
|
||||
QString getTypeAsC(QString name, QString category);
|
||||
|
||||
/**
|
||||
* @brief Adds new types
|
||||
* It first uses the rz_parse_c_string() function from Rizin API to parse the
|
||||
* supplied C file (in the form of a string). If there were errors, they are displayed.
|
||||
* If there were no errors, it uses sdb_query_lines() function from Rizin API
|
||||
* to save the parsed types returned by rz_parse_c_string()
|
||||
* \param str Contains the definition of the data types
|
||||
* \return returns an empty QString if there was no error, else returns the error
|
||||
*/
|
||||
QString addTypes(const char *str);
|
||||
QString addTypes(const QString &str) { return addTypes(str.toUtf8().constData()); }
|
||||
QString getTypeAsC(QString name);
|
||||
|
||||
/**
|
||||
* @brief Checks if the given address is mapped to a region
|
||||
@ -604,14 +644,17 @@ public:
|
||||
|
||||
QList<MemoryMapDescription> getMemoryMap();
|
||||
QList<SearchDescription> getAllSearch(QString searchFor, QString space, QString in);
|
||||
BlockStatistics getBlockStatistics(unsigned int blocksCount);
|
||||
QList<BreakpointDescription> getBreakpoints();
|
||||
QList<ProcessDescription> getAllProcesses();
|
||||
/**
|
||||
* @brief Get the right RzReg object based on the cutter state (debugging vs emulating)
|
||||
*/
|
||||
RzReg *getReg();
|
||||
/**
|
||||
* @brief returns a list of reg values and their telescoped references
|
||||
* @param depth telescoping depth
|
||||
*/
|
||||
QList<QJsonObject> getRegisterRefs(int depth = 6);
|
||||
QList<RegisterRef> getRegisterRefs(int depth = 6);
|
||||
QVector<RegisterRefValueDescription> getRegisterRefValues();
|
||||
QList<VariableDescription> getVariables(RVA at);
|
||||
/**
|
||||
@ -629,8 +672,6 @@ public:
|
||||
QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function,
|
||||
const QString &filterType = QString());
|
||||
|
||||
QList<StringDescription> parseStringsJson(const QJsonDocument &doc);
|
||||
|
||||
void handleREvent(int type, void *data);
|
||||
|
||||
/* Signals related */
|
||||
@ -667,6 +708,10 @@ public:
|
||||
* @brief Commit write cache to the file on disk.
|
||||
*/
|
||||
void commitWriteCache();
|
||||
/**
|
||||
* @brief Reset write cache.
|
||||
*/
|
||||
void resetWriteCache();
|
||||
|
||||
/**
|
||||
* @brief Enable or disable Write mode. When the file is opened in write mode, any changes to it
|
||||
@ -681,6 +726,25 @@ public:
|
||||
*/
|
||||
bool isWriteModeEnabled();
|
||||
|
||||
/**
|
||||
* @brief Returns the textual version of global or specific graph.
|
||||
* @param type Graph type, example RZ_CORE_GRAPH_TYPE_FUNCALL or RZ_CORE_GRAPH_TYPE_IMPORT
|
||||
* @param format Graph format, example RZ_CORE_GRAPH_FORMAT_DOT or RZ_CORE_GRAPH_FORMAT_GML
|
||||
* @param address The object address (if global set it to RVA_INVALID)
|
||||
* @return The textual graph string.
|
||||
*/
|
||||
char *getTextualGraphAt(RzCoreGraphType type, RzCoreGraphFormat format, RVA address);
|
||||
|
||||
/**
|
||||
* @brief Writes a graphviz graph to a file.
|
||||
* @param path The file output path
|
||||
* @param format The output format (see graph.gv.format)
|
||||
* @param type The graph type, example RZ_CORE_GRAPH_TYPE_FUNCALL or
|
||||
* RZ_CORE_GRAPH_TYPE_IMPORT
|
||||
* @param address The object address (if global set it to RVA_INVALID)
|
||||
*/
|
||||
void writeGraphvizGraphToFile(QString path, QString format, RzCoreGraphType type, RVA address);
|
||||
|
||||
signals:
|
||||
void refreshAll();
|
||||
|
||||
@ -736,8 +800,9 @@ signals:
|
||||
/**
|
||||
* @brief seekChanged is emitted each time Rizin's seek value is modified
|
||||
* @param offset
|
||||
* @param historyType
|
||||
*/
|
||||
void seekChanged(RVA offset);
|
||||
void seekChanged(RVA offset, SeekHistoryType type = SeekHistoryType::New);
|
||||
|
||||
void toggleDebugView();
|
||||
|
||||
@ -771,10 +836,11 @@ private:
|
||||
bool iocache = false;
|
||||
BasicInstructionHighlighter biHighlighter;
|
||||
|
||||
QSharedPointer<RizinCmdTask> debugTask;
|
||||
QSharedPointer<RizinTask> debugTask;
|
||||
RizinTaskDialog *debugTaskDialog;
|
||||
|
||||
QVector<QString> getCutterRCFilePaths() const;
|
||||
QList<TypeDescription> getBaseType(RzBaseTypeKind kind, const char *category);
|
||||
};
|
||||
|
||||
class CUTTER_EXPORT RzCoreLocked
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user