mirror of
https://github.com/rizinorg/cutter.git
synced 2024-12-19 11:26:11 +00:00
Merge 'dev' branch into stable
This commit is contained in:
commit
48b35953bb
@ -1,4 +1,4 @@
|
|||||||
version: '2.2.1-git-{build}'
|
version: '2.2.0-git-{build}'
|
||||||
image: 'Visual Studio 2017'
|
image: 'Visual Studio 2017'
|
||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
|
|
||||||
|
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
@ -219,6 +219,7 @@ jobs:
|
|||||||
-DCUTTER_PACKAGE_JSDEC=ON \
|
-DCUTTER_PACKAGE_JSDEC=ON \
|
||||||
-DCUTTER_PACKAGE_RZ_LIBSWIFT=ON \
|
-DCUTTER_PACKAGE_RZ_LIBSWIFT=ON \
|
||||||
-DCUTTER_PACKAGE_RZ_LIBYARA=ON \
|
-DCUTTER_PACKAGE_RZ_LIBYARA=ON \
|
||||||
|
-DCUTTER_PACKAGE_RZ_SILHOUETTE=ON \
|
||||||
-DCMAKE_INSTALL_PREFIX=appdir/usr \
|
-DCMAKE_INSTALL_PREFIX=appdir/usr \
|
||||||
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON \
|
-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=ON \
|
||||||
..
|
..
|
||||||
@ -374,6 +375,7 @@ jobs:
|
|||||||
-DCUTTER_PACKAGE_JSDEC=ON \
|
-DCUTTER_PACKAGE_JSDEC=ON \
|
||||||
-DCUTTER_PACKAGE_RZ_LIBSWIFT=ON \
|
-DCUTTER_PACKAGE_RZ_LIBSWIFT=ON \
|
||||||
-DCUTTER_PACKAGE_RZ_LIBYARA=ON \
|
-DCUTTER_PACKAGE_RZ_LIBYARA=ON \
|
||||||
|
-DCUTTER_PACKAGE_RZ_SILHOUETTE=ON \
|
||||||
-DCPACK_PACKAGE_FILE_NAME="$PACKAGE_NAME" \
|
-DCPACK_PACKAGE_FILE_NAME="$PACKAGE_NAME" \
|
||||||
-DCPACK_BUNDLE_APPLE_CERT_APP="-" \
|
-DCPACK_BUNDLE_APPLE_CERT_APP="-" \
|
||||||
.. && \
|
.. && \
|
||||||
@ -413,6 +415,7 @@ jobs:
|
|||||||
-DCUTTER_PACKAGE_RZ_GHIDRA=ON ^
|
-DCUTTER_PACKAGE_RZ_GHIDRA=ON ^
|
||||||
-DCUTTER_PACKAGE_RZ_LIBSWIFT=ON ^
|
-DCUTTER_PACKAGE_RZ_LIBSWIFT=ON ^
|
||||||
-DCUTTER_PACKAGE_RZ_LIBYARA=ON ^
|
-DCUTTER_PACKAGE_RZ_LIBYARA=ON ^
|
||||||
|
-DCUTTER_PACKAGE_RZ_SILHOUETTE=ON ^
|
||||||
-DCUTTER_PACKAGE_JSDEC=ON ^
|
-DCUTTER_PACKAGE_JSDEC=ON ^
|
||||||
-DCUTTER_ENABLE_DEPENDENCY_DOWNLOADS=ON ^
|
-DCUTTER_ENABLE_DEPENDENCY_DOWNLOADS=ON ^
|
||||||
-DCMAKE_PREFIX_PATH="%CUTTER_DEPS%\pyside" ^
|
-DCMAKE_PREFIX_PATH="%CUTTER_DEPS%\pyside" ^
|
||||||
|
23
.github/workflows/linter.yml
vendored
23
.github/workflows/linter.yml
vendored
@ -26,27 +26,34 @@ jobs:
|
|||||||
- '**.c'
|
- '**.c'
|
||||||
- '**.h'
|
- '**.h'
|
||||||
- '.github/workflows/linter.yml'
|
- '.github/workflows/linter.yml'
|
||||||
|
- 'scripts/clang-format.py'
|
||||||
|
- '_clang-format'
|
||||||
|
|
||||||
clang-format:
|
clang-format:
|
||||||
needs: changes
|
needs: changes
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-22.04
|
||||||
if: ${{ needs.changes.outputs.clang-format == 'true' }}
|
if: ${{ needs.changes.outputs.clang-format == 'true' }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Install wget
|
- name: Install wget, software-properties-common, lsb-release (dependencies of LLVM install script)
|
||||||
run: sudo apt --assume-yes install wget
|
run: sudo apt --assume-yes install wget software-properties-common lsb-release
|
||||||
|
|
||||||
- name: Install automatic llvm (stable branch)
|
- name: Uninstall old conflicting packages
|
||||||
run: sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
|
run: sudo apt purge --assume-yes --auto-remove llvm python3-lldb-14 llvm-14
|
||||||
|
|
||||||
- name: Install clang-format-11
|
- name: Install automatic LLVM 16
|
||||||
run: sudo apt --assume-yes install clang-format-11
|
run: wget https://apt.llvm.org/llvm.sh -O /tmp/llvm-install.sh; chmod +x /tmp/llvm-install.sh; sudo /tmp/llvm-install.sh 16
|
||||||
|
|
||||||
|
- name: Install clang-format-16
|
||||||
|
run: sudo apt --assume-yes install clang-format-16
|
||||||
|
|
||||||
- name: Install gitpython
|
- name: Install gitpython
|
||||||
run: sudo pip install gitpython
|
run: sudo pip install gitpython
|
||||||
|
|
||||||
- name: Run clang-format
|
- name: Run clang-format
|
||||||
run: |
|
run: |
|
||||||
find ./src -regex '.*\.\(cpp\|h\|c\)' -exec clang-format -style=file --dry-run --Werror {} \;
|
sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-16 160
|
||||||
|
clang-format --version
|
||||||
|
python scripts/clang-format.py --check --verbose
|
||||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -94,3 +94,7 @@ docs/source/_build
|
|||||||
# Local gdb files
|
# Local gdb files
|
||||||
.gdb_history
|
.gdb_history
|
||||||
.gdbinit
|
.gdbinit
|
||||||
|
|
||||||
|
# Kdevelop
|
||||||
|
.kdev/
|
||||||
|
*.kdev4
|
||||||
|
@ -28,6 +28,7 @@ pipeline:
|
|||||||
-DCUTTER_PACKAGE_JSDEC=ON
|
-DCUTTER_PACKAGE_JSDEC=ON
|
||||||
-DCUTTER_PACKAGE_RZ_LIBSWIFT=ON
|
-DCUTTER_PACKAGE_RZ_LIBSWIFT=ON
|
||||||
-DCUTTER_PACKAGE_RZ_LIBYARA=ON
|
-DCUTTER_PACKAGE_RZ_LIBYARA=ON
|
||||||
|
-DCUTTER_PACKAGE_RZ_SILHOUETTE=ON
|
||||||
-DCPACK_PACKAGE_FILE_NAME="$$PACKAGE_NAME"
|
-DCPACK_PACKAGE_FILE_NAME="$$PACKAGE_NAME"
|
||||||
-DCPACK_BUNDLE_APPLE_CERT_APP="-"
|
-DCPACK_BUNDLE_APPLE_CERT_APP="-"
|
||||||
- ninja -C build
|
- ninja -C build
|
||||||
|
@ -14,7 +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.\
|
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)
|
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 "Enable Python integration. Requires Python >= ${CUTTER_PYTHON_MIN}." OFF)
|
||||||
option(CUTTER_ENABLE_PYTHON_BINDINGS "Enable generating Python bindings with Shiboken2. Unused if CUTTER_ENABLE_PYTHON=OFF." OFF)
|
option(CUTTER_ENABLE_PYTHON_BINDINGS "Enable generating Python bindings with Shiboken. Unused if CUTTER_ENABLE_PYTHON=OFF." OFF)
|
||||||
option(CUTTER_APPIMAGE_BUILD "Enable Appimage specific changes. Doesn't cause building of Appimage itself." 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_KSYNTAXHIGHLIGHTING "Use KSyntaxHighlighting" AUTO)
|
||||||
tri_option(CUTTER_ENABLE_GRAPHVIZ "Enable use of graphviz for graph layout" AUTO)
|
tri_option(CUTTER_ENABLE_GRAPHVIZ "Enable use of graphviz for graph layout" AUTO)
|
||||||
@ -27,6 +27,7 @@ option(CUTTER_PACKAGE_DEPENDENCIES "During install step include the third party
|
|||||||
option(CUTTER_PACKAGE_RZ_GHIDRA "Compile and install rz-ghidra during install step." 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_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_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_PACKAGE_JSDEC "Compile and install jsdec during install step." OFF)
|
||||||
OPTION(CUTTER_QT6 "Use QT6" OFF)
|
OPTION(CUTTER_QT6 "Use QT6" OFF)
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ endif()
|
|||||||
|
|
||||||
set(CUTTER_VERSION_MAJOR 2)
|
set(CUTTER_VERSION_MAJOR 2)
|
||||||
set(CUTTER_VERSION_MINOR 2)
|
set(CUTTER_VERSION_MINOR 2)
|
||||||
set(CUTTER_VERSION_PATCH 1)
|
set(CUTTER_VERSION_PATCH 0)
|
||||||
|
|
||||||
set(CUTTER_VERSION "${CUTTER_VERSION_MAJOR}.${CUTTER_VERSION_MINOR}.${CUTTER_VERSION_PATCH}")
|
set(CUTTER_VERSION "${CUTTER_VERSION_MAJOR}.${CUTTER_VERSION_MINOR}.${CUTTER_VERSION_PATCH}")
|
||||||
|
|
||||||
@ -99,6 +100,24 @@ if(CUTTER_ENABLE_PYTHON)
|
|||||||
add_definitions(-DCUTTER_ENABLE_PYTHON)
|
add_definitions(-DCUTTER_ENABLE_PYTHON)
|
||||||
|
|
||||||
if(CUTTER_ENABLE_PYTHON_BINDINGS)
|
if(CUTTER_ENABLE_PYTHON_BINDINGS)
|
||||||
|
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()
|
||||||
# 5.12.3 => 5.12
|
# 5.12.3 => 5.12
|
||||||
if("${Qt5_VERSION}" MATCHES "^([0-9]+\\.[0-9]+)\\.[0-9]+")
|
if("${Qt5_VERSION}" MATCHES "^([0-9]+\\.[0-9]+)\\.[0-9]+")
|
||||||
set(Shiboken2_VERSION_REQUIRED "${CMAKE_MATCH_1}")
|
set(Shiboken2_VERSION_REQUIRED "${CMAKE_MATCH_1}")
|
||||||
@ -107,19 +126,21 @@ if(CUTTER_ENABLE_PYTHON)
|
|||||||
endif()
|
endif()
|
||||||
find_package(Shiboken2 "${Shiboken2_VERSION_REQUIRED}" REQUIRED)
|
find_package(Shiboken2 "${Shiboken2_VERSION_REQUIRED}" REQUIRED)
|
||||||
find_package(PySide2 "${Shiboken2_VERSION_REQUIRED}" REQUIRED)
|
find_package(PySide2 "${Shiboken2_VERSION_REQUIRED}" REQUIRED)
|
||||||
|
get_target_property(PYSIDE_INCLUDE_DIRS PySide2::pyside2 INTERFACE_INCLUDE_DIRECTORIES)
|
||||||
|
endif()
|
||||||
|
|
||||||
get_target_property(PYSIDE_INCLUDE_DIR PySide2::pyside2 INTERFACE_INCLUDE_DIRECTORIES)
|
foreach(_dir IN LISTS PYSIDE_INCLUDE_DIRS)
|
||||||
list(GET PYSIDE_INCLUDE_DIR 0 PYSIDE_INCLUDE_DIR)
|
include_directories(${_dir}
|
||||||
include_directories(${PYSIDE_INCLUDE_DIR}
|
${_dir}/QtCore
|
||||||
${PYSIDE_INCLUDE_DIR}/QtCore
|
${_dir}/QtGui
|
||||||
${PYSIDE_INCLUDE_DIR}/QtGui
|
${_dir}/QtWidgets)
|
||||||
${PYSIDE_INCLUDE_DIR}/QtWidgets)
|
endforeach()
|
||||||
|
|
||||||
add_definitions(-DCUTTER_ENABLE_PYTHON_BINDINGS)
|
add_definitions(-DCUTTER_ENABLE_PYTHON_BINDINGS)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CUTTER_ENABLE_KSYNTAXHIGHLIGHTING)
|
if(CUTTER_ENABLE_KSYNTAXHIGHLIGHTING AND (NOT CUTTER_QT6))
|
||||||
if(CUTTER_ENABLE_KSYNTAXHIGHLIGHTING STREQUAL AUTO)
|
if(CUTTER_ENABLE_KSYNTAXHIGHLIGHTING STREQUAL AUTO)
|
||||||
find_package(KF5SyntaxHighlighting)
|
find_package(KF5SyntaxHighlighting)
|
||||||
if(KF5SyntaxHighlighting_FOUND)
|
if(KF5SyntaxHighlighting_FOUND)
|
||||||
@ -132,6 +153,9 @@ if(CUTTER_ENABLE_KSYNTAXHIGHLIGHTING)
|
|||||||
set(KSYNTAXHIGHLIGHTING_STATUS ON)
|
set(KSYNTAXHIGHLIGHTING_STATUS ON)
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
|
if(CUTTER_ENABLE_KSYNTAXHIGHLIGHTING AND CUTTER_QT6)
|
||||||
|
message(WARNING "KSyntaxHighlighting has been disabled because not supported in QT6")
|
||||||
|
endif()
|
||||||
set(KSYNTAXHIGHLIGHTING_STATUS OFF)
|
set(KSYNTAXHIGHLIGHTING_STATUS OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@ -161,6 +185,7 @@ message(STATUS "- Package Dependencies: ${CUTTER_PACKAGE_DEPENDENCIES}")
|
|||||||
message(STATUS "- Package RzGhidra: ${CUTTER_PACKAGE_RZ_GHIDRA}")
|
message(STATUS "- Package RzGhidra: ${CUTTER_PACKAGE_RZ_GHIDRA}")
|
||||||
message(STATUS "- Package RzLibSwift: ${CUTTER_PACKAGE_RZ_LIBSWIFT}")
|
message(STATUS "- Package RzLibSwift: ${CUTTER_PACKAGE_RZ_LIBSWIFT}")
|
||||||
message(STATUS "- Package RzLibYara: ${CUTTER_PACKAGE_RZ_LIBYARA}")
|
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 "- Package JSDec: ${CUTTER_PACKAGE_JSDEC}")
|
||||||
message(STATUS "- QT6: ${CUTTER_QT6}")
|
message(STATUS "- QT6: ${CUTTER_QT6}")
|
||||||
message(STATUS "")
|
message(STATUS "")
|
||||||
|
@ -57,7 +57,7 @@ endif()
|
|||||||
|
|
||||||
# TODO: This version number should be fetched automatically
|
# TODO: This version number should be fetched automatically
|
||||||
# instead of being hardcoded.
|
# instead of being hardcoded.
|
||||||
set (Rizin_VERSION 0.5)
|
set (Rizin_VERSION 0.6)
|
||||||
|
|
||||||
set (RZ_LIBS rz_core rz_config rz_cons rz_io rz_util rz_flag rz_asm rz_debug
|
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_il rz_analysis rz_parse rz_bp rz_egg rz_reg
|
rz_hash rz_bin rz_lang rz_il rz_analysis rz_parse rz_bp rz_egg rz_reg
|
||||||
|
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)
|
@ -14,6 +14,7 @@ set(TS_FILES
|
|||||||
translations/ro/cutter_ro.ts
|
translations/ro/cutter_ro.ts
|
||||||
translations/ru/cutter_ru.ts
|
translations/ru/cutter_ru.ts
|
||||||
translations/tr/cutter_tr.ts
|
translations/tr/cutter_tr.ts
|
||||||
|
translations/uk/cutter_uk.ts
|
||||||
translations/zh-CN/cutter_zh.ts
|
translations/zh-CN/cutter_zh.ts
|
||||||
)
|
)
|
||||||
# translations/ko/cutter_ko.ts problems with fonts
|
# translations/ko/cutter_ko.ts problems with fonts
|
||||||
|
30
dist/CMakeLists.txt
vendored
30
dist/CMakeLists.txt
vendored
@ -7,7 +7,7 @@ unset(RZ_GHIDRA_PREFIX_PATH)
|
|||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(CPACK_GENERATOR "ZIP")
|
set(CPACK_GENERATOR "ZIP")
|
||||||
set(RIZIN_INSTALL_PLUGDIR "lib/plugins")
|
set(RIZIN_INSTALL_PLUGDIR "lib/rizin/plugins")
|
||||||
|
|
||||||
if (CUTTER_PACKAGE_DEPENDENCIES)
|
if (CUTTER_PACKAGE_DEPENDENCIES)
|
||||||
if (CUTTER_ENABLE_PYTHON)
|
if (CUTTER_ENABLE_PYTHON)
|
||||||
@ -59,6 +59,18 @@ if(WIN32)
|
|||||||
endif()
|
endif()
|
||||||
")
|
")
|
||||||
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()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
################################################
|
################################################
|
||||||
@ -150,6 +162,18 @@ if(CUTTER_ENABLE_DEPENDENCY_DOWNLOADS AND (NOT WIN32))
|
|||||||
endif()
|
endif()
|
||||||
")
|
")
|
||||||
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()
|
endif()
|
||||||
|
|
||||||
################################################
|
################################################
|
||||||
@ -164,9 +188,9 @@ if(CUTTER_PACKAGE_RZ_GHIDRA)
|
|||||||
# installed Cutter.
|
# installed Cutter.
|
||||||
ExternalProject_Add(rz-ghidra
|
ExternalProject_Add(rz-ghidra
|
||||||
GIT_REPOSITORY https://github.com/rizinorg/rz-ghidra
|
GIT_REPOSITORY https://github.com/rizinorg/rz-ghidra
|
||||||
GIT_TAG v0.5.0
|
#GIT_TAG v0.3.0
|
||||||
#GIT_TAG c7a50a2e7c0a95cd52b167c9ee0fa1805223f08e
|
#GIT_TAG c7a50a2e7c0a95cd52b167c9ee0fa1805223f08e
|
||||||
#GIT_TAG dev
|
GIT_TAG dev
|
||||||
#GIT_SHALLOW ON # disable this line when using commit hash
|
#GIT_SHALLOW ON # disable this line when using commit hash
|
||||||
CONFIGURE_COMMAND ""
|
CONFIGURE_COMMAND ""
|
||||||
BUILD_COMMAND ""
|
BUILD_COMMAND ""
|
||||||
|
7
dist/bundle_jsdec.ps1
vendored
7
dist/bundle_jsdec.ps1
vendored
@ -5,12 +5,13 @@ if (-not (Test-Path -Path 'jsdec' -PathType Container)) {
|
|||||||
git clone https://github.com/rizinorg/jsdec.git --depth 1 --branch master
|
git clone https://github.com/rizinorg/jsdec.git --depth 1 --branch master
|
||||||
}
|
}
|
||||||
cd jsdec
|
cd jsdec
|
||||||
& meson.exe --buildtype=release -Dc_args=-DDUK_USE_DATE_NOW_WINDOWS -Djsc_folder=".." --prefix=$dist p build
|
& meson.exe --buildtype=release -Dc_args=-DDUK_USE_DATE_NOW_WINDOWS -Djsc_folder=".." --prefix="$dist" p build
|
||||||
ninja -C build install
|
ninja -C build install
|
||||||
$ErrorActionPreference = 'Stop'
|
$ErrorActionPreference = 'Stop'
|
||||||
$pathdll = "$dist\lib\plugins\core_pdd.dll"
|
$pathdll = "$dist\lib\rizin\plugins\core_pdd.dll"
|
||||||
if(![System.IO.File]::Exists($pathdll)) {
|
if(![System.IO.File]::Exists($pathdll)) {
|
||||||
type build\meson-logs\meson-log.txt
|
type build\meson-logs\meson-log.txt
|
||||||
|
ls "$dist\lib\rizin\plugins\"
|
||||||
throw (New-Object System.IO.FileNotFoundException("File not found: $pathdll", $pathdll))
|
throw (New-Object System.IO.FileNotFoundException("File not found: $pathdll", $pathdll))
|
||||||
}
|
}
|
||||||
Remove-Item -Recurse -Force $dist\lib\plugins\core_pdd.lib
|
Remove-Item -Recurse -Force "$dist\lib\rizin\plugins\core_pdd.lib"
|
||||||
|
6
dist/bundle_rz_libswift.ps1
vendored
6
dist/bundle_rz_libswift.ps1
vendored
@ -7,10 +7,10 @@ if (-not (Test-Path -Path 'libswift' -PathType Container)) {
|
|||||||
cd libswift
|
cd libswift
|
||||||
& meson.exe --buildtype=release --prefix=$dist build
|
& meson.exe --buildtype=release --prefix=$dist build
|
||||||
ninja -C build install
|
ninja -C build install
|
||||||
$pathdll = "$dist/lib/plugins/swift.dll"
|
$pathdll = "$dist\lib\rizin\plugins\swift.dll"
|
||||||
if(![System.IO.File]::Exists($pathdll)) {
|
if(![System.IO.File]::Exists($pathdll)) {
|
||||||
type build/meson-logs/meson-log.txt
|
type build/meson-logs/meson-log.txt
|
||||||
ls "$dist/lib/plugins/"
|
ls "$dist\lib\rizin\plugins\"
|
||||||
throw (New-Object System.IO.FileNotFoundException("File not found: $pathdll", $pathdll))
|
throw (New-Object System.IO.FileNotFoundException("File not found: $pathdll", $pathdll))
|
||||||
}
|
}
|
||||||
Remove-Item -Recurse -Force $dist/lib/plugins/swift.lib
|
Remove-Item -Recurse -Force "$dist\lib\rizin\plugins\swift.lib"
|
||||||
|
8
dist/bundle_rz_libyara.ps1
vendored
8
dist/bundle_rz_libyara.ps1
vendored
@ -8,15 +8,15 @@ if (-not (Test-Path -Path 'rz_libyara' -PathType Container)) {
|
|||||||
git -C rz_libyara submodule update
|
git -C rz_libyara submodule update
|
||||||
}
|
}
|
||||||
cd rz_libyara
|
cd rz_libyara
|
||||||
& meson.exe --buildtype=release --prefix=$dist build
|
& meson.exe --buildtype=release --prefix=$dist -Duse_sys_yara=disabled -Denable_openssl=false build
|
||||||
ninja -C build install
|
ninja -C build install
|
||||||
$pathdll = "$dist/lib/plugins/rz_yara.dll"
|
$pathdll = "$dist\lib\rizin\plugins\rz_yara.dll"
|
||||||
if(![System.IO.File]::Exists($pathdll)) {
|
if(![System.IO.File]::Exists($pathdll)) {
|
||||||
type build/meson-logs/meson-log.txt
|
type build/meson-logs/meson-log.txt
|
||||||
ls "$dist/lib/plugins/"
|
ls "$dist\lib\rizin\plugins\"
|
||||||
throw (New-Object System.IO.FileNotFoundException("File not found: $pathdll", $pathdll))
|
throw (New-Object System.IO.FileNotFoundException("File not found: $pathdll", $pathdll))
|
||||||
}
|
}
|
||||||
Remove-Item -Recurse -Force $dist/lib/plugins/rz_yara.lib
|
Remove-Item -Recurse -Force "$dist\lib\rizin\plugins\rz_yara.lib"
|
||||||
|
|
||||||
cd cutter-plugin
|
cd cutter-plugin
|
||||||
mkdir build
|
mkdir build
|
||||||
|
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"
|
@ -247,7 +247,7 @@ Note that there are some major building options available:
|
|||||||
|
|
||||||
* ``CUTTER_USE_BUNDLED_RIZIN`` automatically compile Rizin from submodule (Enabled by default).
|
* ``CUTTER_USE_BUNDLED_RIZIN`` automatically compile Rizin from submodule (Enabled by default).
|
||||||
* ``CUTTER_ENABLE_PYTHON`` compile with Python support.
|
* ``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_KSYNTAXHIGHLIGHTING`` use KSyntaxHighlighting for code highlighting.
|
||||||
* ``CUTTER_ENABLE_GRAPHVIZ`` enable Graphviz for graph layouts.
|
* ``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_EXTRA_PLUGIN_DIRS`` List of addition plugin locations. Useful when preparing package for Linux distros that have strict package layout rules.
|
||||||
|
@ -26,7 +26,7 @@ author = 'The Cutter Developers'
|
|||||||
# The short X.Y version
|
# The short X.Y version
|
||||||
version = '2.2'
|
version = '2.2'
|
||||||
# The full version, including a2lpha/beta/rc tags
|
# The full version, including a2lpha/beta/rc tags
|
||||||
release = '2.2.1'
|
release = '2.2.0'
|
||||||
|
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
|
@ -40,21 +40,45 @@ Options
|
|||||||
**2**
|
**2**
|
||||||
aaaa (experimental)
|
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>
|
.. 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>
|
.. 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>
|
.. option:: -i <file>
|
||||||
|
|
||||||
Run script file
|
Run script file.
|
||||||
|
|
||||||
.. option:: -p, --project <file>
|
.. option:: -p, --project <file>
|
||||||
|
|
||||||
Load project file
|
Load project file.
|
||||||
|
|
||||||
.. option:: -w, --writemode
|
.. option:: -w, --writemode
|
||||||
|
|
||||||
@ -62,9 +86,13 @@ Options
|
|||||||
When used together with -A/--analysis <level>, it will open a file directly
|
When used together with -A/--analysis <level>, it will open a file directly
|
||||||
in write mode without any further dialog or confirmation.
|
in write mode without any further dialog or confirmation.
|
||||||
|
|
||||||
|
.. option:: -P, --phymode
|
||||||
|
|
||||||
|
Disables virtual addressing.
|
||||||
|
|
||||||
.. option:: --pythonhome <PYTHONHOME>
|
.. option:: --pythonhome <PYTHONHOME>
|
||||||
|
|
||||||
PYTHONHOME to use for the embedded python interpreter
|
PYTHONHOME to use for the embedded python interpreter.
|
||||||
|
|
||||||
.. option:: --no-output-redirect
|
.. option:: --no-output-redirect
|
||||||
|
|
||||||
|
2
rizin
2
rizin
@ -1 +1 @@
|
|||||||
Subproject commit e2646b53b0f1aba8202f98b22d345ae73ad0e35f
|
Subproject commit 48b088056236254356fdde46f28d1cbe8bc28316
|
123
scripts/clang-format.py
Executable file
123
scripts/clang-format.py
Executable file
@ -0,0 +1,123 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2021 Anton Kochkov <anton.kochkov@gmail.com>
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import glob
|
||||||
|
import itertools
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from git import Repo
|
||||||
|
|
||||||
|
dirlist = [
|
||||||
|
"src",
|
||||||
|
]
|
||||||
|
|
||||||
|
skiplist = [
|
||||||
|
"translations",
|
||||||
|
]
|
||||||
|
|
||||||
|
patterns = ["*.cpp", "*.h", "*.hpp"]
|
||||||
|
|
||||||
|
|
||||||
|
def should_scan(filename):
|
||||||
|
return any(directory in filename for directory in dirlist) and any(
|
||||||
|
pattern[1:] in filename for pattern in patterns
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def skip(filename):
|
||||||
|
return any(skipfile in filename for skipfile in skiplist)
|
||||||
|
|
||||||
|
|
||||||
|
def get_matching_files():
|
||||||
|
for directory, pattern in itertools.product(dirlist, patterns):
|
||||||
|
for filename in glob.iglob(directory + "/**/" + pattern, recursive=True):
|
||||||
|
if not skip(filename):
|
||||||
|
yield filename
|
||||||
|
|
||||||
|
|
||||||
|
def get_edited_files(args):
|
||||||
|
repo = Repo()
|
||||||
|
|
||||||
|
for diff in repo.index.diff(args.diff):
|
||||||
|
filename = diff.a_path
|
||||||
|
if should_scan(filename) and not skip(filename):
|
||||||
|
yield filename
|
||||||
|
|
||||||
|
|
||||||
|
def build_command(clangformat, check, filenames, verbose):
|
||||||
|
cmd = [clangformat, "--style=file"]
|
||||||
|
if verbose:
|
||||||
|
cmd += ["--verbose"]
|
||||||
|
if check:
|
||||||
|
cmd += ["--Werror", "--dry-run"]
|
||||||
|
else:
|
||||||
|
cmd += ["-i"]
|
||||||
|
return cmd + filenames
|
||||||
|
|
||||||
|
|
||||||
|
def format_files(args, files):
|
||||||
|
if len(files) == 0:
|
||||||
|
print("No C files to format.")
|
||||||
|
sys.exit(0)
|
||||||
|
cmd = build_command(args.clang_format, args.check, files, args.verbose)
|
||||||
|
r = subprocess.run(cmd, check=False)
|
||||||
|
sys.exit(r.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
def get_file(args):
|
||||||
|
filename = args.file
|
||||||
|
if should_scan(filename) and not skip(filename):
|
||||||
|
return [filename]
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
def get_files(args):
|
||||||
|
if args.diff:
|
||||||
|
return get_edited_files(args)
|
||||||
|
|
||||||
|
if args.file:
|
||||||
|
return get_file(args)
|
||||||
|
|
||||||
|
return get_matching_files()
|
||||||
|
|
||||||
|
|
||||||
|
def process(args):
|
||||||
|
files = get_files(args)
|
||||||
|
format_files(args, list(files))
|
||||||
|
|
||||||
|
|
||||||
|
def parse():
|
||||||
|
parser = argparse.ArgumentParser(description="Clang format the rizin project")
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-C", "--clang-format", default="clang-format", help="path of clang-format"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-c", "--check", action="store_true", help="enable the check mode"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-v", "--verbose", action="store_true", help="use verbose output"
|
||||||
|
)
|
||||||
|
parser.add_argument("-f", "--file", help="formats (or checks) only the given file")
|
||||||
|
parser.add_argument(
|
||||||
|
"-d",
|
||||||
|
"--diff",
|
||||||
|
type=str,
|
||||||
|
default=None,
|
||||||
|
help="format all modified file related to branch",
|
||||||
|
)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = parse()
|
||||||
|
process(args)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
@ -15,7 +15,7 @@ fi
|
|||||||
|
|
||||||
cd rz_libyara
|
cd rz_libyara
|
||||||
|
|
||||||
meson --buildtype=release --pkg-config-path="$INSTALL_PREFIX/lib/pkgconfig" --prefix="$INSTALL_PREFIX" build
|
meson --buildtype=release --pkg-config-path="$INSTALL_PREFIX/lib/pkgconfig" --prefix="$INSTALL_PREFIX" -Duse_sys_yara=disabled build
|
||||||
ninja -C build install
|
ninja -C build install
|
||||||
|
|
||||||
cd cutter-plugin
|
cd cutter-plugin
|
||||||
|
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
|
@ -6,6 +6,7 @@ set(SOURCES
|
|||||||
core/Cutter.cpp
|
core/Cutter.cpp
|
||||||
core/CutterJson.cpp
|
core/CutterJson.cpp
|
||||||
core/RizinCpp.cpp
|
core/RizinCpp.cpp
|
||||||
|
core/Basefind.cpp
|
||||||
dialogs/EditStringDialog.cpp
|
dialogs/EditStringDialog.cpp
|
||||||
dialogs/WriteCommandsDialogs.cpp
|
dialogs/WriteCommandsDialogs.cpp
|
||||||
widgets/DisassemblerGraphView.cpp
|
widgets/DisassemblerGraphView.cpp
|
||||||
@ -17,6 +18,7 @@ set(SOURCES
|
|||||||
dialogs/CommentsDialog.cpp
|
dialogs/CommentsDialog.cpp
|
||||||
dialogs/EditInstructionDialog.cpp
|
dialogs/EditInstructionDialog.cpp
|
||||||
dialogs/FlagDialog.cpp
|
dialogs/FlagDialog.cpp
|
||||||
|
dialogs/GlobalVariableDialog.cpp
|
||||||
dialogs/RemoteDebugDialog.cpp
|
dialogs/RemoteDebugDialog.cpp
|
||||||
dialogs/NativeDebugDialog.cpp
|
dialogs/NativeDebugDialog.cpp
|
||||||
dialogs/XrefsDialog.cpp
|
dialogs/XrefsDialog.cpp
|
||||||
@ -35,6 +37,7 @@ set(SOURCES
|
|||||||
widgets/ExportsWidget.cpp
|
widgets/ExportsWidget.cpp
|
||||||
widgets/FlagsWidget.cpp
|
widgets/FlagsWidget.cpp
|
||||||
widgets/FunctionsWidget.cpp
|
widgets/FunctionsWidget.cpp
|
||||||
|
widgets/GlobalsWidget.cpp
|
||||||
widgets/ImportsWidget.cpp
|
widgets/ImportsWidget.cpp
|
||||||
widgets/Omnibar.cpp
|
widgets/Omnibar.cpp
|
||||||
widgets/RelocsWidget.cpp
|
widgets/RelocsWidget.cpp
|
||||||
@ -149,6 +152,9 @@ set(SOURCES
|
|||||||
dialogs/GlibcHeapBinsDialog.cpp
|
dialogs/GlibcHeapBinsDialog.cpp
|
||||||
widgets/HeapBinsGraphView.cpp
|
widgets/HeapBinsGraphView.cpp
|
||||||
dialogs/ArenaInfoDialog.cpp
|
dialogs/ArenaInfoDialog.cpp
|
||||||
|
tools/basefind/BaseFindDialog.cpp
|
||||||
|
tools/basefind/BaseFindSearchDialog.cpp
|
||||||
|
tools/basefind/BaseFindResultsDialog.cpp
|
||||||
)
|
)
|
||||||
set(HEADER_FILES
|
set(HEADER_FILES
|
||||||
core/Cutter.h
|
core/Cutter.h
|
||||||
@ -156,6 +162,7 @@ set(HEADER_FILES
|
|||||||
core/CutterDescriptions.h
|
core/CutterDescriptions.h
|
||||||
core/CutterJson.h
|
core/CutterJson.h
|
||||||
core/RizinCpp.h
|
core/RizinCpp.h
|
||||||
|
core/Basefind.h
|
||||||
dialogs/EditStringDialog.h
|
dialogs/EditStringDialog.h
|
||||||
dialogs/WriteCommandsDialogs.h
|
dialogs/WriteCommandsDialogs.h
|
||||||
widgets/DisassemblerGraphView.h
|
widgets/DisassemblerGraphView.h
|
||||||
@ -167,6 +174,7 @@ set(HEADER_FILES
|
|||||||
dialogs/CommentsDialog.h
|
dialogs/CommentsDialog.h
|
||||||
dialogs/EditInstructionDialog.h
|
dialogs/EditInstructionDialog.h
|
||||||
dialogs/FlagDialog.h
|
dialogs/FlagDialog.h
|
||||||
|
dialogs/GlobalVariableDialog.h
|
||||||
dialogs/RemoteDebugDialog.h
|
dialogs/RemoteDebugDialog.h
|
||||||
dialogs/NativeDebugDialog.h
|
dialogs/NativeDebugDialog.h
|
||||||
dialogs/XrefsDialog.h
|
dialogs/XrefsDialog.h
|
||||||
@ -308,6 +316,9 @@ set(HEADER_FILES
|
|||||||
dialogs/GlibcHeapBinsDialog.h
|
dialogs/GlibcHeapBinsDialog.h
|
||||||
widgets/HeapBinsGraphView.h
|
widgets/HeapBinsGraphView.h
|
||||||
dialogs/ArenaInfoDialog.h
|
dialogs/ArenaInfoDialog.h
|
||||||
|
tools/basefind/BaseFindDialog.h
|
||||||
|
tools/basefind/BaseFindSearchDialog.h
|
||||||
|
tools/basefind/BaseFindResultsDialog.h
|
||||||
)
|
)
|
||||||
set(UI_FILES
|
set(UI_FILES
|
||||||
dialogs/AboutDialog.ui
|
dialogs/AboutDialog.ui
|
||||||
@ -319,6 +330,7 @@ set(UI_FILES
|
|||||||
dialogs/CommentsDialog.ui
|
dialogs/CommentsDialog.ui
|
||||||
dialogs/EditInstructionDialog.ui
|
dialogs/EditInstructionDialog.ui
|
||||||
dialogs/FlagDialog.ui
|
dialogs/FlagDialog.ui
|
||||||
|
dialogs/GlobalVariableDialog.ui
|
||||||
dialogs/RemoteDebugDialog.ui
|
dialogs/RemoteDebugDialog.ui
|
||||||
dialogs/NativeDebugDialog.ui
|
dialogs/NativeDebugDialog.ui
|
||||||
dialogs/XrefsDialog.ui
|
dialogs/XrefsDialog.ui
|
||||||
@ -330,6 +342,7 @@ set(UI_FILES
|
|||||||
widgets/Dashboard.ui
|
widgets/Dashboard.ui
|
||||||
widgets/EntrypointWidget.ui
|
widgets/EntrypointWidget.ui
|
||||||
widgets/FlagsWidget.ui
|
widgets/FlagsWidget.ui
|
||||||
|
widgets/GlobalsWidget.ui
|
||||||
widgets/StringsWidget.ui
|
widgets/StringsWidget.ui
|
||||||
widgets/HexdumpWidget.ui
|
widgets/HexdumpWidget.ui
|
||||||
dialogs/preferences/PreferencesDialog.ui
|
dialogs/preferences/PreferencesDialog.ui
|
||||||
@ -338,7 +351,6 @@ set(UI_FILES
|
|||||||
dialogs/preferences/InitializationFileEditor.ui
|
dialogs/preferences/InitializationFileEditor.ui
|
||||||
widgets/QuickFilterView.ui
|
widgets/QuickFilterView.ui
|
||||||
widgets/DecompilerWidget.ui
|
widgets/DecompilerWidget.ui
|
||||||
widgets/ClassesWidget.ui
|
|
||||||
widgets/VTablesWidget.ui
|
widgets/VTablesWidget.ui
|
||||||
widgets/TypesWidget.ui
|
widgets/TypesWidget.ui
|
||||||
widgets/SearchWidget.ui
|
widgets/SearchWidget.ui
|
||||||
@ -378,6 +390,9 @@ set(UI_FILES
|
|||||||
widgets/GlibcHeapWidget.ui
|
widgets/GlibcHeapWidget.ui
|
||||||
dialogs/GlibcHeapBinsDialog.ui
|
dialogs/GlibcHeapBinsDialog.ui
|
||||||
dialogs/ArenaInfoDialog.ui
|
dialogs/ArenaInfoDialog.ui
|
||||||
|
tools/basefind/BaseFindDialog.ui
|
||||||
|
tools/basefind/BaseFindSearchDialog.ui
|
||||||
|
tools/basefind/BaseFindResultsDialog.ui
|
||||||
)
|
)
|
||||||
set(QRC_FILES
|
set(QRC_FILES
|
||||||
resources.qrc
|
resources.qrc
|
||||||
@ -387,16 +402,26 @@ set(QRC_FILES
|
|||||||
themes/lightstyle/light.qrc
|
themes/lightstyle/light.qrc
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(CUTTER_INCLUDE_DIRECTORIES core widgets common plugins menus .)
|
||||||
|
|
||||||
if (CUTTER_ENABLE_PYTHON)
|
if (CUTTER_ENABLE_PYTHON)
|
||||||
list(APPEND SOURCES common/QtResImporter.cpp common/PythonManager.cpp common/PythonAPI.cpp)
|
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)
|
list(APPEND HEADER_FILES common/QtResImporter.h common/PythonManager.h common/PythonAPI.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CUTTER_ENABLE_PYTHON_BINDINGS)
|
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_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/bindings")
|
||||||
set(BINDINGS_BUILD_DIR "${CMAKE_CURRENT_BINARY_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)
|
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "${BINDINGS_SRC_DIR}/src_list.py" cmake "${BINDINGS_BUILD_DIR}" OUTPUT_VARIABLE BINDINGS_SOURCE)
|
||||||
|
|
||||||
@ -404,14 +429,40 @@ if(CUTTER_ENABLE_PYTHON_BINDINGS)
|
|||||||
|
|
||||||
include_directories("${BINDINGS_BUILD_DIR}/CutterBindings")
|
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)
|
set(SHIBOKEN_OPTIONS)
|
||||||
|
list(APPEND SHIBOKEN_OPTIONS --include-paths="${SHIBOKEN_INCLUDE_DIRS}")
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
list(APPEND SHIBOKEN_OPTIONS --avoid-protected-hack)
|
list(APPEND SHIBOKEN_OPTIONS --avoid-protected-hack)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_custom_command(OUTPUT ${BINDINGS_SOURCE}
|
add_custom_command(OUTPUT ${BINDINGS_SOURCE}
|
||||||
COMMAND Shiboken2::shiboken2 --project-file="${BINDINGS_BUILD_DIR}/bindings.txt" ${SHIBOKEN_OPTIONS} ${SHIBOKEN_EXTRA_OPTIONS}
|
COMMAND "${SHIBOKEN_COMMAND}" --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"
|
DEPENDS "${BINDINGS_BUILD_DIR}/bindings.xml" "${BINDINGS_BUILD_DIR}/bindings.txt"
|
||||||
IMPLICIT_DEPENDS CXX "${CMAKE_CURRENT_SOURCE_DIR}/bindings/bindings.h"
|
IMPLICIT_DEPENDS CXX "${CMAKE_CURRENT_SOURCE_DIR}/bindings/bindings.h"
|
||||||
COMMENT "Generating Python bindings with shiboken2")
|
COMMENT "Generating Python bindings with shiboken2")
|
||||||
else()
|
else()
|
||||||
@ -453,7 +504,6 @@ target_compile_definitions(Cutter PRIVATE CUTTER_SOURCE_BUILD)
|
|||||||
# Set Cutter as the startup project in Visual Studio
|
# Set Cutter as the startup project in Visual Studio
|
||||||
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Cutter)
|
set_property(DIRECTORY ${PROJECT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Cutter)
|
||||||
|
|
||||||
set(CUTTER_INCLUDE_DIRECTORIES core widgets common plugins menus .)
|
|
||||||
foreach(_dir ${CUTTER_INCLUDE_DIRECTORIES})
|
foreach(_dir ${CUTTER_INCLUDE_DIRECTORIES})
|
||||||
target_include_directories(Cutter PUBLIC
|
target_include_directories(Cutter PUBLIC
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${_dir}>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/${_dir}>
|
||||||
@ -488,7 +538,11 @@ if(CUTTER_ENABLE_PYTHON)
|
|||||||
endif()
|
endif()
|
||||||
target_link_libraries(Cutter PRIVATE ${PYTHON_LIBRARIES})
|
target_link_libraries(Cutter PRIVATE ${PYTHON_LIBRARIES})
|
||||||
if(CUTTER_ENABLE_PYTHON_BINDINGS)
|
if(CUTTER_ENABLE_PYTHON_BINDINGS)
|
||||||
|
if (CUTTER_QT6)
|
||||||
|
target_link_libraries(Cutter PRIVATE Shiboken6::libshiboken PySide6::pyside6)
|
||||||
|
else()
|
||||||
target_link_libraries(Cutter PRIVATE Shiboken2::libshiboken PySide2::pyside2)
|
target_link_libraries(Cutter PRIVATE Shiboken2::libshiboken PySide2::pyside2)
|
||||||
|
endif()
|
||||||
|
|
||||||
get_target_property(RAW_BINDINGS_INCLUDE_DIRS Cutter INCLUDE_DIRECTORIES)
|
get_target_property(RAW_BINDINGS_INCLUDE_DIRS Cutter INCLUDE_DIRECTORIES)
|
||||||
if(NOT CUTTER_USE_BUNDLED_RIZIN)
|
if(NOT CUTTER_USE_BUNDLED_RIZIN)
|
||||||
@ -510,7 +564,11 @@ if(CUTTER_ENABLE_PYTHON)
|
|||||||
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include/QtGui")
|
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include/QtGui")
|
||||||
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include/QtWidgets")
|
list(APPEND BINDINGS_INCLUDE_DIRS "${_qt5Core_install_prefix}/include/QtWidgets")
|
||||||
endif()
|
endif()
|
||||||
|
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})
|
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 ${Rizin_INCLUDE_DIRS})
|
||||||
list(APPEND BINDINGS_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
|
list(APPEND BINDINGS_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
|
@ -162,7 +162,8 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc
|
|||||||
appdir.cdUp(); // appdir
|
appdir.cdUp(); // appdir
|
||||||
|
|
||||||
auto sleighHome = appdir;
|
auto sleighHome = appdir;
|
||||||
sleighHome.cd("lib/rizin/plugins/rz_ghidra_sleigh/"); // appdir/lib/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());
|
Core()->setConfig("ghidra.sleighhome", sleighHome.absolutePath());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -174,8 +175,8 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc
|
|||||||
rzprefix.cd("Resources"); // Contents/Resources/
|
rzprefix.cd("Resources"); // Contents/Resources/
|
||||||
|
|
||||||
auto sleighHome = rzprefix;
|
auto sleighHome = rzprefix;
|
||||||
sleighHome.cd(
|
// Contents/Resources/lib/rizin/plugins/rz_ghidra_sleigh
|
||||||
"lib/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());
|
Core()->setConfig("ghidra.sleighhome", sleighHome.absolutePath());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -183,7 +184,7 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc
|
|||||||
#if defined(Q_OS_WIN) && defined(CUTTER_ENABLE_PACKAGING)
|
#if defined(Q_OS_WIN) && defined(CUTTER_ENABLE_PACKAGING)
|
||||||
{
|
{
|
||||||
auto sleighHome = QDir(QCoreApplication::applicationDirPath());
|
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());
|
Core()->setConfig("ghidra.sleighhome", sleighHome.absolutePath());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -295,6 +296,89 @@ bool CutterApplication::loadTranslations()
|
|||||||
return false;
|
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()
|
bool CutterApplication::parseCommandLineOptions()
|
||||||
{
|
{
|
||||||
// Keep this function in sync with documentation
|
// Keep this function in sync with documentation
|
||||||
@ -314,6 +398,27 @@ bool CutterApplication::parseCommandLineOptions()
|
|||||||
QObject::tr("level"));
|
QObject::tr("level"));
|
||||||
cmd_parser.addOption(analOption);
|
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" },
|
QCommandLineOption formatOption({ "F", "format" },
|
||||||
QObject::tr("Force using a specific file format (bin plugin)"),
|
QObject::tr("Force using a specific file format (bin plugin)"),
|
||||||
QObject::tr("name"));
|
QObject::tr("name"));
|
||||||
@ -324,6 +429,11 @@ bool CutterApplication::parseCommandLineOptions()
|
|||||||
QObject::tr("base address"));
|
QObject::tr("base address"));
|
||||||
cmd_parser.addOption(baddrOption);
|
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"));
|
QCommandLineOption scriptOption("i", QObject::tr("Run script file"), QObject::tr("file"));
|
||||||
cmd_parser.addOption(scriptOption);
|
cmd_parser.addOption(scriptOption);
|
||||||
|
|
||||||
@ -335,6 +445,10 @@ bool CutterApplication::parseCommandLineOptions()
|
|||||||
QObject::tr("Open file in write mode"));
|
QObject::tr("Open file in write mode"));
|
||||||
cmd_parser.addOption(writeModeOption);
|
cmd_parser.addOption(writeModeOption);
|
||||||
|
|
||||||
|
QCommandLineOption phyModeOption({ "P", "phymode" },
|
||||||
|
QObject::tr("Disables virtual addressing"));
|
||||||
|
cmd_parser.addOption(phyModeOption);
|
||||||
|
|
||||||
QCommandLineOption pythonHomeOption(
|
QCommandLineOption pythonHomeOption(
|
||||||
"pythonhome", QObject::tr("PYTHONHOME to use for embedded python interpreter"),
|
"pythonhome", QObject::tr("PYTHONHOME to use for embedded python interpreter"),
|
||||||
"PYTHONHOME");
|
"PYTHONHOME");
|
||||||
@ -396,15 +510,21 @@ bool CutterApplication::parseCommandLineOptions()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
InitialOptions options;
|
|
||||||
if (!opts.args.isEmpty()) {
|
if (!opts.args.isEmpty()) {
|
||||||
opts.fileOpenOptions.filename = opts.args[0];
|
opts.fileOpenOptions.filename = opts.args[0];
|
||||||
opts.fileOpenOptions.forceBinPlugin = cmd_parser.value(formatOption);
|
opts.fileOpenOptions.forceBinPlugin = cmd_parser.value(formatOption);
|
||||||
if (cmd_parser.isSet(baddrOption)) {
|
if (cmd_parser.isSet(baddrOption)) {
|
||||||
bool ok;
|
bool ok = false;
|
||||||
RVA baddr = cmd_parser.value(baddrOption).toULongLong(&ok, 0);
|
RVA baddr = cmd_parser.value(baddrOption).toULongLong(&ok, 0);
|
||||||
if (ok) {
|
if (ok) {
|
||||||
options.binLoadAddr = baddr;
|
opts.fileOpenOptions.binLoadAddr = baddr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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) {
|
switch (opts.analysisLevel) {
|
||||||
@ -421,8 +541,36 @@ bool CutterApplication::parseCommandLineOptions()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
opts.fileOpenOptions.script = cmd_parser.value(scriptOption);
|
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.writeEnabled = cmd_parser.isSet(writeModeOption);
|
||||||
|
opts.fileOpenOptions.useVA = !cmd_parser.isSet(phyModeOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
opts.fileOpenOptions.projectFile = cmd_parser.value(projectOption);
|
opts.fileOpenOptions.projectFile = cmd_parser.value(projectOption);
|
||||||
|
@ -33,6 +33,10 @@ public:
|
|||||||
|
|
||||||
void launchNewInstance(const QStringList &args = {});
|
void launchNewInstance(const QStringList &args = {});
|
||||||
|
|
||||||
|
InitialOptions getInitialOptions() const { return clOptions.fileOpenOptions; }
|
||||||
|
void setInitialOptions(const InitialOptions &options) { clOptions.fileOpenOptions = options; }
|
||||||
|
QStringList getArgs() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool event(QEvent *e);
|
bool event(QEvent *e);
|
||||||
|
|
||||||
|
@ -67,9 +67,9 @@ int main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
QCoreApplication::setApplicationName("cutter");
|
QCoreApplication::setApplicationName("cutter");
|
||||||
|
|
||||||
// Importing settings after setting rename, needs separate handling in addition to regular version to version upgrade.
|
// Importing settings after setting rename, needs separate handling in addition to regular
|
||||||
if (Cutter::shouldOfferSettingImport())
|
// version to version upgrade.
|
||||||
{
|
if (Cutter::shouldOfferSettingImport()) {
|
||||||
Cutter::showSettingImportDialog(argc, argv);
|
Cutter::showSettingImportDialog(argc, argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
generator-set = shiboken
|
generator-set = shiboken
|
||||||
|
|
||||||
header-file = ${BINDINGS_SRC_DIR}/bindings.h
|
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}
|
output-directory = ${BINDINGS_BUILD_DIR}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
PyErr_Print();
|
PyErr_Print();
|
||||||
return QString();
|
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) {
|
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);
|
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();
|
return ::QString();
|
@ -9,7 +9,7 @@ script_path = os.path.dirname(os.path.realpath(__file__))
|
|||||||
|
|
||||||
|
|
||||||
def get_cpp_files_gen(args, include_package=True):
|
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()
|
ts_root = ts_tree.getroot()
|
||||||
|
|
||||||
package = ts_root.attrib["package"]
|
package = ts_root.attrib["package"]
|
||||||
|
@ -13,11 +13,17 @@ AddressableFilterProxyModel::AddressableFilterProxyModel(AddressableItemModelI *
|
|||||||
|
|
||||||
RVA AddressableFilterProxyModel::address(const QModelIndex &index) const
|
RVA AddressableFilterProxyModel::address(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
|
if (!addressableSourceModel) {
|
||||||
|
return RVA_INVALID;
|
||||||
|
}
|
||||||
return addressableSourceModel->address(this->mapToSource(index));
|
return addressableSourceModel->address(this->mapToSource(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AddressableFilterProxyModel::name(const QModelIndex &index) const
|
QString AddressableFilterProxyModel::name(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
|
if (!addressableSourceModel) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
return addressableSourceModel->name(this->mapToSource(index));
|
return addressableSourceModel->name(this->mapToSource(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,6 +34,6 @@ void AddressableFilterProxyModel::setSourceModel(QAbstractItemModel *)
|
|||||||
|
|
||||||
void AddressableFilterProxyModel::setSourceModel(AddressableItemModelI *sourceModel)
|
void AddressableFilterProxyModel::setSourceModel(AddressableItemModelI *sourceModel)
|
||||||
{
|
{
|
||||||
ParentClass::setSourceModel(sourceModel->asItemModel());
|
ParentClass::setSourceModel(sourceModel ? sourceModel->asItemModel() : nullptr);
|
||||||
addressableSourceModel = sourceModel;
|
addressableSourceModel = sourceModel;
|
||||||
}
|
}
|
||||||
|
@ -783,6 +783,16 @@ bool Configuration::getPreviewValue() const
|
|||||||
return s.value("asm.preview").toBool();
|
return s.value("asm.preview").toBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Configuration::setShowVarTooltips(bool enabled)
|
||||||
|
{
|
||||||
|
s.setValue("showVarTooltips", enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Configuration::getShowVarTooltips() const
|
||||||
|
{
|
||||||
|
return s.value("showVarTooltips").toBool();
|
||||||
|
}
|
||||||
|
|
||||||
bool Configuration::getGraphBlockEntryOffset()
|
bool Configuration::getGraphBlockEntryOffset()
|
||||||
{
|
{
|
||||||
return s.value("graphBlockEntryOffset", true).value<bool>();
|
return s.value("graphBlockEntryOffset", true).value<bool>();
|
||||||
|
@ -215,6 +215,12 @@ public:
|
|||||||
void setPreviewValue(bool checked);
|
void setPreviewValue(bool checked);
|
||||||
bool getPreviewValue() const;
|
bool getPreviewValue() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Show tooltips for known values of registers, variables, and memory when debugging
|
||||||
|
*/
|
||||||
|
void setShowVarTooltips(bool enabled);
|
||||||
|
bool getShowVarTooltips() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Recently opened binaries, as shown in NewFileDialog.
|
* @brief Recently opened binaries, as shown in NewFileDialog.
|
||||||
*/
|
*/
|
||||||
|
@ -13,18 +13,18 @@ CutterSeekable::~CutterSeekable() {}
|
|||||||
void CutterSeekable::setSynchronization(bool sync)
|
void CutterSeekable::setSynchronization(bool sync)
|
||||||
{
|
{
|
||||||
synchronized = sync;
|
synchronized = sync;
|
||||||
onCoreSeekChanged(Core()->getOffset());
|
onCoreSeekChanged(Core()->getOffset(), CutterCore::SeekHistoryType::New);
|
||||||
emit syncChanged();
|
emit syncChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterSeekable::onCoreSeekChanged(RVA addr)
|
void CutterSeekable::onCoreSeekChanged(RVA addr, CutterCore::SeekHistoryType type)
|
||||||
{
|
{
|
||||||
if (synchronized && widgetOffset != addr) {
|
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;
|
previousOffset = widgetOffset;
|
||||||
widgetOffset = addr;
|
widgetOffset = addr;
|
||||||
@ -32,7 +32,7 @@ void CutterSeekable::updateSeek(RVA addr, bool localOnly)
|
|||||||
Core()->seek(addr);
|
Core()->seek(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit seekableSeekChanged(addr);
|
emit seekableSeekChanged(addr, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterSeekable::seekPrev()
|
void CutterSeekable::seekPrev()
|
||||||
@ -40,7 +40,7 @@ void CutterSeekable::seekPrev()
|
|||||||
if (synchronized) {
|
if (synchronized) {
|
||||||
Core()->seekPrev();
|
Core()->seekPrev();
|
||||||
} else {
|
} else {
|
||||||
this->seek(previousOffset);
|
this->seek(previousOffset, CutterCore::SeekHistoryType::Undo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,12 @@ public:
|
|||||||
* signal will be emitted.
|
* signal will be emitted.
|
||||||
* In any case, CutterSeekable::seekableSeekChanged is emitted.
|
* In any case, CutterSeekable::seekableSeekChanged is emitted.
|
||||||
* @param addr the location to seek at.
|
* @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
|
* @brief setSynchronization sets
|
||||||
@ -67,7 +71,7 @@ private slots:
|
|||||||
/**
|
/**
|
||||||
* @brief onCoreSeekChanged
|
* @brief onCoreSeekChanged
|
||||||
*/
|
*/
|
||||||
void onCoreSeekChanged(RVA addr);
|
void onCoreSeekChanged(RVA addr, CutterCore::SeekHistoryType type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
@ -91,9 +95,9 @@ private:
|
|||||||
* @brief internal method for changing the seek
|
* @brief internal method for changing the seek
|
||||||
* @param localOnly whether the seek should be updated globally if synchronized
|
* @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:
|
signals:
|
||||||
void seekableSeekChanged(RVA addr);
|
void seekableSeekChanged(RVA addr, CutterCore::SeekHistoryType type);
|
||||||
void syncChanged();
|
void syncChanged();
|
||||||
};
|
};
|
||||||
|
@ -82,3 +82,75 @@ RVA DisassemblyPreview::readDisassemblyOffset(QTextCursor tc)
|
|||||||
|
|
||||||
return userData->line.offset;
|
return userData->line.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct mmio_lookup_context
|
||||||
|
{
|
||||||
|
QString selected;
|
||||||
|
RVA mmio_address;
|
||||||
|
} mmio_lookup_context_t;
|
||||||
|
|
||||||
|
static bool lookup_mmio_addr_cb(void *user, const ut64 key, const void *value)
|
||||||
|
{
|
||||||
|
mmio_lookup_context_t *ctx = (mmio_lookup_context_t *)user;
|
||||||
|
if (ctx->selected == (const char *)value) {
|
||||||
|
ctx->mmio_address = key;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DisassemblyPreview::showDebugValueTooltip(QWidget *parent, const QPoint &pointOfEvent,
|
||||||
|
const QString &selectedText, const RVA offset)
|
||||||
|
{
|
||||||
|
if (selectedText.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (selectedText.at(0).isLetter()) {
|
||||||
|
{
|
||||||
|
const auto registerRefs = Core()->getRegisterRefValues();
|
||||||
|
for (auto ® : registerRefs) {
|
||||||
|
if (reg.name == selectedText) {
|
||||||
|
auto msg = QString("reg %1 = %2").arg(reg.name, reg.value);
|
||||||
|
QToolTip::showText(pointOfEvent, msg, parent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset != RVA_INVALID) {
|
||||||
|
auto vars = Core()->getVariables(offset);
|
||||||
|
for (auto &var : vars) {
|
||||||
|
if (var.name == selectedText) {
|
||||||
|
auto msg = QString("var %1 = %2").arg(var.name, var.value);
|
||||||
|
QToolTip::showText(pointOfEvent, msg, parent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// Lookup MMIO address
|
||||||
|
mmio_lookup_context_t ctx;
|
||||||
|
ctx.selected = selectedText;
|
||||||
|
ctx.mmio_address = RVA_INVALID;
|
||||||
|
auto core = Core()->core();
|
||||||
|
RzPlatformTarget *arch_target = core->analysis->arch_target;
|
||||||
|
if (arch_target && arch_target->profile) {
|
||||||
|
ht_up_foreach(arch_target->profile->registers_mmio, lookup_mmio_addr_cb, &ctx);
|
||||||
|
}
|
||||||
|
if (ctx.mmio_address != RVA_INVALID) {
|
||||||
|
int len = 8; // TODO: Determine proper len of mmio address for the cpu
|
||||||
|
if (char *r = rz_core_print_hexdump_or_hexdiff_str(core, RZ_OUTPUT_MODE_STANDARD,
|
||||||
|
ctx.mmio_address, len, false)) {
|
||||||
|
auto val = QString::fromUtf8(r).trimmed().split("\n").last();
|
||||||
|
auto msg = QString("mmio %1 %2").arg(selectedText, val);
|
||||||
|
free(r);
|
||||||
|
QToolTip::showText(pointOfEvent, msg, parent);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Else show preview for value?
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -41,5 +41,13 @@ bool showDisasPreview(QWidget *parent, const QPoint &pointOfEvent, const RVA off
|
|||||||
* @return The disassembly offset of the hovered asm text
|
* @return The disassembly offset of the hovered asm text
|
||||||
*/
|
*/
|
||||||
RVA readDisassemblyOffset(QTextCursor tc);
|
RVA readDisassemblyOffset(QTextCursor tc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Show a QToolTip that shows the value of the highlighted register, variable, or memory
|
||||||
|
* @return True if the tooltip is shown
|
||||||
|
*/
|
||||||
|
bool showDebugValueTooltip(QWidget *parent, const QPoint &pointOfEvent, const QString &selectedText,
|
||||||
|
const RVA offset);
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,7 +32,7 @@ PyObject *api_refresh(PyObject *self, PyObject *args)
|
|||||||
Q_UNUSED(self);
|
Q_UNUSED(self);
|
||||||
Q_UNUSED(args);
|
Q_UNUSED(args);
|
||||||
Core()->triggerRefreshAll();
|
Core()->triggerRefreshAll();
|
||||||
return Py_None;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *api_message(PyObject *self, PyObject *args, PyObject *kwargs)
|
PyObject *api_message(PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
@ -46,8 +46,7 @@ PyObject *api_message(PyObject *self, PyObject *args, PyObject *kwargs)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
Core()->message(QString(message), debug);
|
Core()->message(QString(message), debug);
|
||||||
Py_INCREF(Py_None);
|
Py_RETURN_NONE;
|
||||||
return Py_None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyMethodDef CutterMethods[] = {
|
PyMethodDef CutterMethods[] = {
|
||||||
|
@ -13,6 +13,10 @@
|
|||||||
#ifdef CUTTER_ENABLE_PYTHON_BINDINGS
|
#ifdef CUTTER_ENABLE_PYTHON_BINDINGS
|
||||||
# include <shiboken.h>
|
# include <shiboken.h>
|
||||||
# include <pyside.h>
|
# include <pyside.h>
|
||||||
|
# ifdef HAVE_PYSIDECLEANUP
|
||||||
|
// This header is introduced in PySide 6
|
||||||
|
# include <pysidecleanup.h>
|
||||||
|
# endif
|
||||||
# include <signalmanager.h>
|
# include <signalmanager.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -72,7 +76,10 @@ void PythonManager::initialize()
|
|||||||
PyImport_AppendInittab("CutterBindings", &PyInit_CutterBindings);
|
PyImport_AppendInittab("CutterBindings", &PyInit_CutterBindings);
|
||||||
#endif
|
#endif
|
||||||
Py_Initialize();
|
Py_Initialize();
|
||||||
|
// This function is deprecated does nothing starting from Python 3.9
|
||||||
|
#if (PY_MAJOR_VERSION <= 3) && (PY_MICRO_VERSION < 9)
|
||||||
PyEval_InitThreads();
|
PyEval_InitThreads();
|
||||||
|
#endif
|
||||||
pyThreadStateCounter = 1; // we have the thread now => 1
|
pyThreadStateCounter = 1; // we have the thread now => 1
|
||||||
|
|
||||||
RegQtResImporter();
|
RegQtResImporter();
|
||||||
@ -159,7 +166,7 @@ void PythonManager::addPythonPath(char *path)
|
|||||||
if (!append) {
|
if (!append) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PyEval_CallFunction(append, "(s)", path);
|
PyObject_CallFunction(append, "(s)", path);
|
||||||
|
|
||||||
saveThread();
|
saveThread();
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@
|
|||||||
namespace Cutter {
|
namespace Cutter {
|
||||||
void initializeSettings();
|
void initializeSettings();
|
||||||
/**
|
/**
|
||||||
* @brief Check if Cutter should offer importing settings from version that can't be directly updated.
|
* @brief Check if Cutter should offer importing settings from version that can't be directly
|
||||||
|
* updated.
|
||||||
* @return True if this is first time running Cutter and r2 based Cutter <= 1.12 settings exist.
|
* @return True if this is first time running Cutter and r2 based Cutter <= 1.12 settings exist.
|
||||||
*/
|
*/
|
||||||
bool shouldOfferSettingImport();
|
bool shouldOfferSettingImport();
|
||||||
|
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() << tr("Start address is >= end address");
|
||||||
|
return false;
|
||||||
|
} else if (options.alignment < RZ_BASEFIND_BASE_ALIGNMENT) {
|
||||||
|
qWarning() << tr("Alignment must be at least ")
|
||||||
|
<< QString::asprintf("0x%x", RZ_BASEFIND_BASE_ALIGNMENT);
|
||||||
|
return false;
|
||||||
|
} else if (options.min_score < 1) {
|
||||||
|
qWarning() << tr("Min score must be at least 1");
|
||||||
|
return false;
|
||||||
|
} else if (options.min_string_len < 1) {
|
||||||
|
qWarning() << tr("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
|
@ -271,7 +271,7 @@ void CutterCore::loadCutterRC()
|
|||||||
if (!cutterRCFileInfo.exists() || !cutterRCFileInfo.isFile()) {
|
if (!cutterRCFileInfo.exists() || !cutterRCFileInfo.isFile()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
qInfo() << "Loading initialization file from " << cutterRCFilePath;
|
qInfo() << tr("Loading initialization file from ") << cutterRCFilePath;
|
||||||
rz_core_cmd_file(core, cutterRCFilePath.toUtf8().constData());
|
rz_core_cmd_file(core, cutterRCFilePath.toUtf8().constData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,7 +284,7 @@ void CutterCore::loadDefaultCutterRC()
|
|||||||
if (!cutterRCFileInfo.exists() || !cutterRCFileInfo.isFile()) {
|
if (!cutterRCFileInfo.exists() || !cutterRCFileInfo.isFile()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qInfo() << "Loading initialization file from " << cutterRCFilePath;
|
qInfo() << tr("Loading initialization file from ") << cutterRCFilePath;
|
||||||
rz_core_cmd_file(core, cutterRCFilePath.toUtf8().constData());
|
rz_core_cmd_file(core, cutterRCFilePath.toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1002,19 +1002,19 @@ void CutterCore::seekPrev()
|
|||||||
{
|
{
|
||||||
CORE_LOCK();
|
CORE_LOCK();
|
||||||
rz_core_seek_undo(core);
|
rz_core_seek_undo(core);
|
||||||
updateSeek();
|
updateSeek(SeekHistoryType::Undo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::seekNext()
|
void CutterCore::seekNext()
|
||||||
{
|
{
|
||||||
CORE_LOCK();
|
CORE_LOCK();
|
||||||
rz_core_seek_redo(core);
|
rz_core_seek_redo(core);
|
||||||
updateSeek();
|
updateSeek(SeekHistoryType::Redo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CutterCore::updateSeek()
|
void CutterCore::updateSeek(SeekHistoryType type)
|
||||||
{
|
{
|
||||||
emit seekChanged(getOffset());
|
emit seekChanged(getOffset(), type);
|
||||||
}
|
}
|
||||||
|
|
||||||
RVA CutterCore::prevOpAddr(RVA startAddr, int count)
|
RVA CutterCore::prevOpAddr(RVA startAddr, int count)
|
||||||
@ -1804,11 +1804,43 @@ QList<VariableDescription> CutterCore::getVariables(RVA at)
|
|||||||
}
|
}
|
||||||
desc.type = QString::fromUtf8(tn);
|
desc.type = QString::fromUtf8(tn);
|
||||||
rz_mem_free(tn);
|
rz_mem_free(tn);
|
||||||
|
|
||||||
|
if (char *v = rz_core_analysis_var_display(core, var, false)) {
|
||||||
|
desc.value = QString::fromUtf8(v).trimmed();
|
||||||
|
rz_mem_free(v);
|
||||||
|
}
|
||||||
|
|
||||||
ret.push_back(desc);
|
ret.push_back(desc);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<GlobalDescription> CutterCore::getAllGlobals()
|
||||||
|
{
|
||||||
|
CORE_LOCK();
|
||||||
|
RzListIter *it;
|
||||||
|
|
||||||
|
QList<GlobalDescription> ret;
|
||||||
|
|
||||||
|
RzAnalysisVarGlobal *glob;
|
||||||
|
if (core && core->analysis && core->analysis->typedb) {
|
||||||
|
const RzList *globals = rz_analysis_var_global_get_all(core->analysis);
|
||||||
|
CutterRzListForeach (globals, it, RzAnalysisVarGlobal, glob) {
|
||||||
|
const char *gtype = rz_type_as_string(core->analysis->typedb, glob->type);
|
||||||
|
if (!gtype) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
GlobalDescription global;
|
||||||
|
global.addr = glob->addr;
|
||||||
|
global.name = QString(glob->name);
|
||||||
|
global.type = QString(gtype);
|
||||||
|
ret << global;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
QVector<RegisterRefValueDescription> CutterCore::getRegisterRefValues()
|
QVector<RegisterRefValueDescription> CutterCore::getRegisterRefValues()
|
||||||
{
|
{
|
||||||
QVector<RegisterRefValueDescription> result;
|
QVector<RegisterRefValueDescription> result;
|
||||||
@ -3084,8 +3116,6 @@ QList<ImportDescription> CutterCore::getAllImports()
|
|||||||
RzBinImport *import;
|
RzBinImport *import;
|
||||||
RzListIter *iter;
|
RzListIter *iter;
|
||||||
bool va = core->io->va || core->bin->is_debugger;
|
bool va = core->io->va || core->bin->is_debugger;
|
||||||
int bin_demangle = getConfigi("bin.demangle");
|
|
||||||
int keep_lib = getConfigi("bin.demangle.libs");
|
|
||||||
CutterRzListForeach (imports, iter, RzBinImport, import) {
|
CutterRzListForeach (imports, iter, RzBinImport, import) {
|
||||||
if (RZ_STR_ISEMPTY(import->name)) {
|
if (RZ_STR_ISEMPTY(import->name)) {
|
||||||
continue;
|
continue;
|
||||||
@ -3099,13 +3129,6 @@ QList<ImportDescription> CutterCore::getAllImports()
|
|||||||
if (RZ_STR_ISNOTEMPTY(import->classname)) {
|
if (RZ_STR_ISNOTEMPTY(import->classname)) {
|
||||||
name = QString("%1.%2").arg(import->classname, import->name);
|
name = QString("%1.%2").arg(import->classname, import->name);
|
||||||
}
|
}
|
||||||
if (bin_demangle) {
|
|
||||||
char *dname = rz_bin_demangle(bf, NULL, name.toUtf8().constData(),
|
|
||||||
importDescription.plt, keep_lib);
|
|
||||||
if (dname) {
|
|
||||||
name = fromOwnedCharPtr(dname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (core->bin->prefix) {
|
if (core->bin->prefix) {
|
||||||
name = QString("%1.%2").arg(core->bin->prefix, name);
|
name = QString("%1.%2").arg(core->bin->prefix, name);
|
||||||
}
|
}
|
||||||
@ -3135,8 +3158,8 @@ QList<ExportDescription> CutterCore::getAllExports()
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
QString lang = getConfigi("bin.demangle") ? getConfig("bin.lang") : "";
|
|
||||||
bool va = core->io->va || core->bin->is_debugger;
|
bool va = core->io->va || core->bin->is_debugger;
|
||||||
|
bool demangle = rz_config_get_b(core->config, "bin.demangle");
|
||||||
|
|
||||||
QList<ExportDescription> ret;
|
QList<ExportDescription> ret;
|
||||||
for (const auto &symbol : CutterRzList<RzBinSymbol>(symbols)) {
|
for (const auto &symbol : CutterRzList<RzBinSymbol>(symbols)) {
|
||||||
@ -3145,7 +3168,7 @@ QList<ExportDescription> CutterCore::getAllExports()
|
|||||||
}
|
}
|
||||||
|
|
||||||
RzBinSymNames sn = {};
|
RzBinSymNames sn = {};
|
||||||
rz_core_sym_name_init(core, &sn, symbol, lang.isEmpty() ? NULL : lang.toUtf8().constData());
|
rz_core_sym_name_init(&sn, symbol, demangle);
|
||||||
|
|
||||||
ExportDescription exportDescription;
|
ExportDescription exportDescription;
|
||||||
exportDescription.vaddr = rva(bf->o, symbol->paddr, symbol->vaddr, va);
|
exportDescription.vaddr = rva(bf->o, symbol->paddr, symbol->vaddr, va);
|
||||||
@ -3543,19 +3566,18 @@ QList<BinClassDescription> CutterCore::getAllClassesFromBin()
|
|||||||
RzListIter *iter, *iter2, *iter3;
|
RzListIter *iter, *iter2, *iter3;
|
||||||
RzBinClass *c;
|
RzBinClass *c;
|
||||||
RzBinSymbol *sym;
|
RzBinSymbol *sym;
|
||||||
RzBinField *f;
|
RzBinClassField *f;
|
||||||
CutterRzListForeach (cs, iter, RzBinClass, c) {
|
CutterRzListForeach (cs, iter, RzBinClass, c) {
|
||||||
BinClassDescription classDescription;
|
BinClassDescription classDescription;
|
||||||
classDescription.name = c->name;
|
classDescription.name = c->name;
|
||||||
classDescription.addr = c->addr;
|
classDescription.addr = c->addr;
|
||||||
classDescription.index = c->index;
|
|
||||||
CutterRzListForeach (c->methods, iter2, RzBinSymbol, sym) {
|
CutterRzListForeach (c->methods, iter2, RzBinSymbol, sym) {
|
||||||
BinClassMethodDescription methodDescription;
|
BinClassMethodDescription methodDescription;
|
||||||
methodDescription.name = sym->name;
|
methodDescription.name = sym->name;
|
||||||
methodDescription.addr = sym->vaddr;
|
methodDescription.addr = sym->vaddr;
|
||||||
classDescription.methods << methodDescription;
|
classDescription.methods << methodDescription;
|
||||||
}
|
}
|
||||||
CutterRzListForeach (c->fields, iter3, RzBinField, f) {
|
CutterRzListForeach (c->fields, iter3, RzBinClassField, f) {
|
||||||
BinClassFieldDescription fieldDescription;
|
BinClassFieldDescription fieldDescription;
|
||||||
fieldDescription.name = f->name;
|
fieldDescription.name = f->name;
|
||||||
fieldDescription.addr = f->vaddr;
|
fieldDescription.addr = f->vaddr;
|
||||||
@ -3591,7 +3613,6 @@ QList<BinClassDescription> CutterCore::getAllClassesFromFlags()
|
|||||||
}
|
}
|
||||||
desc->name = match.captured(1);
|
desc->name = match.captured(1);
|
||||||
desc->addr = item.offset;
|
desc->addr = item.offset;
|
||||||
desc->index = RVA_INVALID;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3605,7 +3626,6 @@ QList<BinClassDescription> CutterCore::getAllClassesFromFlags()
|
|||||||
BinClassDescription cls;
|
BinClassDescription cls;
|
||||||
cls.name = tr("Unknown (%1)").arg(className);
|
cls.name = tr("Unknown (%1)").arg(className);
|
||||||
cls.addr = RVA_INVALID;
|
cls.addr = RVA_INVALID;
|
||||||
cls.index = 0;
|
|
||||||
ret << cls;
|
ret << cls;
|
||||||
classDesc = &ret.last();
|
classDesc = &ret.last();
|
||||||
classesCache[className] = classDesc;
|
classesCache[className] = classDesc;
|
||||||
@ -4028,6 +4048,99 @@ QList<XrefDescription> CutterCore::getXRefs(RVA addr, bool to, bool whole_functi
|
|||||||
return xrefList;
|
return xrefList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CutterCore::addGlobalVariable(RVA offset, QString name, QString typ)
|
||||||
|
{
|
||||||
|
name = sanitizeStringForCommand(name);
|
||||||
|
CORE_LOCK();
|
||||||
|
char *errmsg = NULL;
|
||||||
|
RzType *globType = rz_type_parse_string_single(core->analysis->typedb->parser,
|
||||||
|
typ.toStdString().c_str(), &errmsg);
|
||||||
|
if (errmsg) {
|
||||||
|
qWarning() << tr("Error parsing type: \"%1\" message: ").arg(typ) << errmsg;
|
||||||
|
free(errmsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!rz_analysis_var_global_create(core->analysis, name.toStdString().c_str(), globType,
|
||||||
|
offset)) {
|
||||||
|
qWarning() << tr("Error creating global variable: \"%1\"").arg(name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit globalVarsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::modifyGlobalVariable(RVA offset, QString name, QString typ)
|
||||||
|
{
|
||||||
|
name = sanitizeStringForCommand(name);
|
||||||
|
CORE_LOCK();
|
||||||
|
RzAnalysisVarGlobal *glob = rz_analysis_var_global_get_byaddr_at(core->analysis, offset);
|
||||||
|
if (!glob) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Compare if the name is not the same - also rename it
|
||||||
|
if (name.compare(glob->name)) {
|
||||||
|
rz_analysis_var_global_rename(core->analysis, glob->name, name.toStdString().c_str());
|
||||||
|
}
|
||||||
|
char *errmsg = NULL;
|
||||||
|
RzType *globType = rz_type_parse_string_single(core->analysis->typedb->parser,
|
||||||
|
typ.toStdString().c_str(), &errmsg);
|
||||||
|
if (errmsg) {
|
||||||
|
qWarning() << tr("Error parsing type: \"%1\" message: ").arg(typ) << errmsg;
|
||||||
|
free(errmsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rz_analysis_var_global_set_type(glob, globType);
|
||||||
|
|
||||||
|
emit globalVarsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::delGlobalVariable(QString name)
|
||||||
|
{
|
||||||
|
name = sanitizeStringForCommand(name);
|
||||||
|
CORE_LOCK();
|
||||||
|
rz_analysis_var_global_delete_byname(core->analysis, name.toStdString().c_str());
|
||||||
|
|
||||||
|
emit globalVarsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CutterCore::delGlobalVariable(RVA offset)
|
||||||
|
{
|
||||||
|
CORE_LOCK();
|
||||||
|
rz_analysis_var_global_delete_byaddr_at(core->analysis, offset);
|
||||||
|
|
||||||
|
emit globalVarsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CutterCore::getGlobalVariableType(QString name)
|
||||||
|
{
|
||||||
|
name = sanitizeStringForCommand(name);
|
||||||
|
CORE_LOCK();
|
||||||
|
RzAnalysisVarGlobal *glob =
|
||||||
|
rz_analysis_var_global_get_byname(core->analysis, name.toStdString().c_str());
|
||||||
|
if (!glob) {
|
||||||
|
return QString("");
|
||||||
|
}
|
||||||
|
const char *gtype = rz_type_as_string(core->analysis->typedb, glob->type);
|
||||||
|
if (!gtype) {
|
||||||
|
return QString("");
|
||||||
|
}
|
||||||
|
return QString(gtype);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CutterCore::getGlobalVariableType(RVA offset)
|
||||||
|
{
|
||||||
|
CORE_LOCK();
|
||||||
|
RzAnalysisVarGlobal *glob = rz_analysis_var_global_get_byaddr_at(core->analysis, offset);
|
||||||
|
if (!glob) {
|
||||||
|
return QString("");
|
||||||
|
}
|
||||||
|
const char *gtype = rz_type_as_string(core->analysis->typedb, glob->type);
|
||||||
|
if (!gtype) {
|
||||||
|
return QString("");
|
||||||
|
}
|
||||||
|
return QString(gtype);
|
||||||
|
}
|
||||||
|
|
||||||
void CutterCore::addFlag(RVA offset, QString name, RVA size)
|
void CutterCore::addFlag(RVA offset, QString name, RVA size)
|
||||||
{
|
{
|
||||||
name = sanitizeStringForCommand(name);
|
name = sanitizeStringForCommand(name);
|
||||||
@ -4149,11 +4262,20 @@ QList<DisassemblyLine> CutterCore::disassembleLines(RVA offset, int lines)
|
|||||||
|
|
||||||
QList<DisassemblyLine> r;
|
QList<DisassemblyLine> r;
|
||||||
for (const auto &t : CutterPVector<RzAnalysisDisasmText>(vec.get())) {
|
for (const auto &t : CutterPVector<RzAnalysisDisasmText>(vec.get())) {
|
||||||
|
QString text = t->text;
|
||||||
|
QStringList tokens = text.split('\n');
|
||||||
|
// text might contain multiple lines
|
||||||
|
// so we split them and keep only one
|
||||||
|
// arrow/jump to addr.
|
||||||
|
for (const auto &tok : tokens) {
|
||||||
DisassemblyLine line;
|
DisassemblyLine line;
|
||||||
line.offset = t->offset;
|
line.offset = t->offset;
|
||||||
line.text = ansiEscapeToHtml(t->text);
|
line.text = ansiEscapeToHtml(tok);
|
||||||
line.arrow = t->arrow;
|
line.arrow = t->arrow;
|
||||||
r << line;
|
r << line;
|
||||||
|
// only the first one.
|
||||||
|
t->arrow = RVA_INVALID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -4533,9 +4655,9 @@ char *CutterCore::getTextualGraphAt(RzCoreGraphType type, RzCoreGraphFormat form
|
|||||||
RzGraph *graph = rz_core_graph(core, type, address);
|
RzGraph *graph = rz_core_graph(core, type, address);
|
||||||
if (!graph) {
|
if (!graph) {
|
||||||
if (address == RVA_INVALID) {
|
if (address == RVA_INVALID) {
|
||||||
qWarning() << "Cannot get global graph";
|
qWarning() << tr("Cannot get global graph");
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Cannot get graph at " << RzAddressString(address);
|
qWarning() << tr("Cannot get graph at ") << RzAddressString(address);
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -4566,7 +4688,7 @@ char *CutterCore::getTextualGraphAt(RzCoreGraphType type, RzCoreGraphFormat form
|
|||||||
rz_graph_free(graph);
|
rz_graph_free(graph);
|
||||||
|
|
||||||
if (!string) {
|
if (!string) {
|
||||||
qWarning() << "Failed to generate graph";
|
qWarning() << tr("Failed to generate graph");
|
||||||
}
|
}
|
||||||
|
|
||||||
return string;
|
return string;
|
||||||
@ -4584,9 +4706,15 @@ void CutterCore::writeGraphvizGraphToFile(QString path, QString format, RzCoreGr
|
|||||||
|
|
||||||
if (!rz_core_graph_write(core, address, type, filepath)) {
|
if (!rz_core_graph_write(core, address, type, filepath)) {
|
||||||
if (address == RVA_INVALID) {
|
if (address == RVA_INVALID) {
|
||||||
qWarning() << "Cannot get global graph";
|
qWarning() << tr("Cannot get global graph");
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Cannot get graph at " << RzAddressString(address);
|
qWarning() << tr("Cannot get graph at ") << RzAddressString(address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CutterCore::rebaseBin(RVA base_address)
|
||||||
|
{
|
||||||
|
CORE_LOCK();
|
||||||
|
return rz_core_bin_rebase(core, base_address);
|
||||||
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "core/CutterCommon.h"
|
#include "core/CutterCommon.h"
|
||||||
#include "core/CutterDescriptions.h"
|
#include "core/CutterDescriptions.h"
|
||||||
#include "core/CutterJson.h"
|
#include "core/CutterJson.h"
|
||||||
|
#include "core/Basefind.h"
|
||||||
#include "common/BasicInstructionHighlighter.h"
|
#include "common/BasicInstructionHighlighter.h"
|
||||||
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
@ -69,6 +70,7 @@ class CUTTER_EXPORT CutterCore : public QObject
|
|||||||
|
|
||||||
friend class RzCoreLocked;
|
friend class RzCoreLocked;
|
||||||
friend class RizinTask;
|
friend class RizinTask;
|
||||||
|
friend class Basefind;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CutterCore(QObject *parent = nullptr);
|
explicit CutterCore(QObject *parent = nullptr);
|
||||||
@ -172,6 +174,8 @@ public:
|
|||||||
return returner;
|
return returner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class SeekHistoryType { New, Undo, Redo };
|
||||||
|
|
||||||
CutterJson cmdj(const char *str);
|
CutterJson cmdj(const char *str);
|
||||||
CutterJson cmdj(const QString &str) { return cmdj(str.toUtf8().constData()); }
|
CutterJson cmdj(const QString &str) { return cmdj(str.toUtf8().constData()); }
|
||||||
QString cmdTask(const QString &str);
|
QString cmdTask(const QString &str);
|
||||||
@ -235,6 +239,14 @@ public:
|
|||||||
QString nearestFlag(RVA offset, RVA *flagOffsetOut);
|
QString nearestFlag(RVA offset, RVA *flagOffsetOut);
|
||||||
void triggerFlagsChanged();
|
void triggerFlagsChanged();
|
||||||
|
|
||||||
|
/* Global Variables */
|
||||||
|
void addGlobalVariable(RVA offset, QString name, QString typ);
|
||||||
|
void delGlobalVariable(QString name);
|
||||||
|
void delGlobalVariable(RVA offset);
|
||||||
|
void modifyGlobalVariable(RVA offset, QString name, QString typ);
|
||||||
|
QString getGlobalVariableType(QString name);
|
||||||
|
QString getGlobalVariableType(RVA offset);
|
||||||
|
|
||||||
/* Edition functions */
|
/* Edition functions */
|
||||||
PRzAnalysisBytes getRzAnalysisBytesSingle(RVA addr);
|
PRzAnalysisBytes getRzAnalysisBytesSingle(RVA addr);
|
||||||
QString getInstructionBytes(RVA addr);
|
QString getInstructionBytes(RVA addr);
|
||||||
@ -324,7 +336,7 @@ public:
|
|||||||
void seekSilent(QString thing) { seekSilent(math(thing)); }
|
void seekSilent(QString thing) { seekSilent(math(thing)); }
|
||||||
void seekPrev();
|
void seekPrev();
|
||||||
void seekNext();
|
void seekNext();
|
||||||
void updateSeek();
|
void updateSeek(SeekHistoryType type = SeekHistoryType::New);
|
||||||
/**
|
/**
|
||||||
* @brief Raise a memory widget showing current offset, prefer last active
|
* @brief Raise a memory widget showing current offset, prefer last active
|
||||||
* memory widget.
|
* memory widget.
|
||||||
@ -554,6 +566,8 @@ public:
|
|||||||
void setGraphEmpty(bool empty);
|
void setGraphEmpty(bool empty);
|
||||||
bool isGraphEmpty();
|
bool isGraphEmpty();
|
||||||
|
|
||||||
|
bool rebaseBin(RVA base_address);
|
||||||
|
|
||||||
void getRegs();
|
void getRegs();
|
||||||
QList<QString> regs;
|
QList<QString> regs;
|
||||||
void setSettings();
|
void setSettings();
|
||||||
@ -578,6 +592,7 @@ public:
|
|||||||
QList<ExportDescription> getAllExports();
|
QList<ExportDescription> getAllExports();
|
||||||
QList<SymbolDescription> getAllSymbols();
|
QList<SymbolDescription> getAllSymbols();
|
||||||
QList<HeaderDescription> getAllHeaders();
|
QList<HeaderDescription> getAllHeaders();
|
||||||
|
QList<GlobalDescription> getAllGlobals();
|
||||||
QList<FlirtDescription> getSignaturesDB();
|
QList<FlirtDescription> getSignaturesDB();
|
||||||
QList<CommentDescription> getAllComments(const QString &filterType);
|
QList<CommentDescription> getAllComments(const QString &filterType);
|
||||||
QList<RelocDescription> getAllRelocs();
|
QList<RelocDescription> getAllRelocs();
|
||||||
@ -744,6 +759,7 @@ signals:
|
|||||||
|
|
||||||
void functionRenamed(const RVA offset, const QString &new_name);
|
void functionRenamed(const RVA offset, const QString &new_name);
|
||||||
void varsChanged();
|
void varsChanged();
|
||||||
|
void globalVarsChanged();
|
||||||
void functionsChanged();
|
void functionsChanged();
|
||||||
void flagsChanged();
|
void flagsChanged();
|
||||||
void commentsChanged(RVA addr);
|
void commentsChanged(RVA addr);
|
||||||
@ -794,8 +810,9 @@ signals:
|
|||||||
/**
|
/**
|
||||||
* @brief seekChanged is emitted each time Rizin's seek value is modified
|
* @brief seekChanged is emitted each time Rizin's seek value is modified
|
||||||
* @param offset
|
* @param offset
|
||||||
|
* @param historyType
|
||||||
*/
|
*/
|
||||||
void seekChanged(RVA offset);
|
void seekChanged(RVA offset, SeekHistoryType type = SeekHistoryType::New);
|
||||||
|
|
||||||
void toggleDebugView();
|
void toggleDebugView();
|
||||||
|
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
# undef max
|
# undef max
|
||||||
#endif // Q_OS_WIN
|
#endif // Q_OS_WIN
|
||||||
|
|
||||||
|
|
||||||
// Global information for Cutter
|
// Global information for Cutter
|
||||||
#define APPNAME "Cutter"
|
#define APPNAME "Cutter"
|
||||||
|
|
||||||
|
@ -239,7 +239,6 @@ struct BinClassDescription
|
|||||||
QString name;
|
QString name;
|
||||||
RVA addr = RVA_INVALID;
|
RVA addr = RVA_INVALID;
|
||||||
RVA vtableAddr = RVA_INVALID;
|
RVA vtableAddr = RVA_INVALID;
|
||||||
ut64 index = 0;
|
|
||||||
QList<BinClassBaseClassDescription> baseClasses;
|
QList<BinClassBaseClassDescription> baseClasses;
|
||||||
QList<BinClassMethodDescription> methods;
|
QList<BinClassMethodDescription> methods;
|
||||||
QList<BinClassFieldDescription> fields;
|
QList<BinClassFieldDescription> fields;
|
||||||
@ -358,6 +357,14 @@ struct VariableDescription
|
|||||||
RzAnalysisVarStorageType storageType;
|
RzAnalysisVarStorageType storageType;
|
||||||
QString name;
|
QString name;
|
||||||
QString type;
|
QString type;
|
||||||
|
QString value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct GlobalDescription
|
||||||
|
{
|
||||||
|
RVA addr;
|
||||||
|
QString type;
|
||||||
|
QString name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RegisterRefValueDescription
|
struct RegisterRefValueDescription
|
||||||
@ -386,6 +393,18 @@ struct Arena
|
|||||||
ut64 max_system_mem;
|
ut64 max_system_mem;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct BasefindCoreStatusDescription
|
||||||
|
{
|
||||||
|
size_t index;
|
||||||
|
ut32 percentage;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BasefindResultDescription
|
||||||
|
{
|
||||||
|
RVA candidate;
|
||||||
|
ut32 score;
|
||||||
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(FunctionDescription)
|
Q_DECLARE_METATYPE(FunctionDescription)
|
||||||
Q_DECLARE_METATYPE(ImportDescription)
|
Q_DECLARE_METATYPE(ImportDescription)
|
||||||
Q_DECLARE_METATYPE(ExportDescription)
|
Q_DECLARE_METATYPE(ExportDescription)
|
||||||
@ -395,6 +414,7 @@ Q_DECLARE_METATYPE(RelocDescription)
|
|||||||
Q_DECLARE_METATYPE(StringDescription)
|
Q_DECLARE_METATYPE(StringDescription)
|
||||||
Q_DECLARE_METATYPE(FlagspaceDescription)
|
Q_DECLARE_METATYPE(FlagspaceDescription)
|
||||||
Q_DECLARE_METATYPE(FlagDescription)
|
Q_DECLARE_METATYPE(FlagDescription)
|
||||||
|
Q_DECLARE_METATYPE(GlobalDescription)
|
||||||
Q_DECLARE_METATYPE(XrefDescription)
|
Q_DECLARE_METATYPE(XrefDescription)
|
||||||
Q_DECLARE_METATYPE(EntrypointDescription)
|
Q_DECLARE_METATYPE(EntrypointDescription)
|
||||||
Q_DECLARE_METATYPE(RzBinPluginDescription)
|
Q_DECLARE_METATYPE(RzBinPluginDescription)
|
||||||
@ -424,5 +444,7 @@ Q_DECLARE_METATYPE(BreakpointDescription::PositionType)
|
|||||||
Q_DECLARE_METATYPE(ProcessDescription)
|
Q_DECLARE_METATYPE(ProcessDescription)
|
||||||
Q_DECLARE_METATYPE(RefDescription)
|
Q_DECLARE_METATYPE(RefDescription)
|
||||||
Q_DECLARE_METATYPE(VariableDescription)
|
Q_DECLARE_METATYPE(VariableDescription)
|
||||||
|
Q_DECLARE_METATYPE(BasefindCoreStatusDescription)
|
||||||
|
Q_DECLARE_METATYPE(BasefindResultDescription)
|
||||||
|
|
||||||
#endif // DESCRIPTIONS_H
|
#endif // DESCRIPTIONS_H
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "widgets/DisassemblerGraphView.h"
|
#include "widgets/DisassemblerGraphView.h"
|
||||||
#include "widgets/GraphView.h"
|
#include "widgets/GraphView.h"
|
||||||
#include "widgets/GraphWidget.h"
|
#include "widgets/GraphWidget.h"
|
||||||
|
#include "widgets/GlobalsWidget.h"
|
||||||
#include "widgets/OverviewWidget.h"
|
#include "widgets/OverviewWidget.h"
|
||||||
#include "widgets/OverviewView.h"
|
#include "widgets/OverviewView.h"
|
||||||
#include "widgets/FunctionsWidget.h"
|
#include "widgets/FunctionsWidget.h"
|
||||||
@ -115,6 +116,9 @@
|
|||||||
#include <QGraphicsScene>
|
#include <QGraphicsScene>
|
||||||
#include <QGraphicsView>
|
#include <QGraphicsView>
|
||||||
|
|
||||||
|
// Tools
|
||||||
|
#include "tools/basefind/BaseFindDialog.h"
|
||||||
|
|
||||||
#define PROJECT_FILE_FILTER tr("Rizin Project (*.rzdb)")
|
#define PROJECT_FILE_FILTER tr("Rizin Project (*.rzdb)")
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
@ -268,7 +272,7 @@ void MainWindow::initUI()
|
|||||||
readSettings();
|
readSettings();
|
||||||
|
|
||||||
// Display tooltip for the Analyze Program action
|
// Display tooltip for the Analyze Program action
|
||||||
ui->actionAnalyze->setToolTip("Analyze the program using Rizin's \"aaa\" command");
|
ui->actionAnalyze->setToolTip(tr("Analyze the program using Rizin's \"aaa\" command"));
|
||||||
ui->menuFile->setToolTipsVisible(true);
|
ui->menuFile->setToolTipsVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,6 +402,7 @@ void MainWindow::initDocks()
|
|||||||
sectionsDock = new SectionsWidget(this),
|
sectionsDock = new SectionsWidget(this),
|
||||||
segmentsDock = new SegmentsWidget(this),
|
segmentsDock = new SegmentsWidget(this),
|
||||||
symbolsDock = new SymbolsWidget(this),
|
symbolsDock = new SymbolsWidget(this),
|
||||||
|
globalsDock = new GlobalsWidget(this),
|
||||||
vTablesDock = new VTablesWidget(this),
|
vTablesDock = new VTablesWidget(this),
|
||||||
flirtDock = new FlirtWidget(this),
|
flirtDock = new FlirtWidget(this),
|
||||||
rzGraphDock = new RizinGraphWidget(this),
|
rzGraphDock = new RizinGraphWidget(this),
|
||||||
@ -902,6 +907,7 @@ void MainWindow::restoreDocks()
|
|||||||
tabifyDockWidget(dashboardDock, headersDock);
|
tabifyDockWidget(dashboardDock, headersDock);
|
||||||
tabifyDockWidget(dashboardDock, flirtDock);
|
tabifyDockWidget(dashboardDock, flirtDock);
|
||||||
tabifyDockWidget(dashboardDock, symbolsDock);
|
tabifyDockWidget(dashboardDock, symbolsDock);
|
||||||
|
tabifyDockWidget(dashboardDock, globalsDock);
|
||||||
tabifyDockWidget(dashboardDock, classesDock);
|
tabifyDockWidget(dashboardDock, classesDock);
|
||||||
tabifyDockWidget(dashboardDock, resourcesDock);
|
tabifyDockWidget(dashboardDock, resourcesDock);
|
||||||
tabifyDockWidget(dashboardDock, vTablesDock);
|
tabifyDockWidget(dashboardDock, vTablesDock);
|
||||||
@ -1637,6 +1643,12 @@ void MainWindow::on_actionTabs_triggered()
|
|||||||
setTabLocation();
|
setTabLocation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::on_actionBaseFind_triggered()
|
||||||
|
{
|
||||||
|
auto dialog = new BaseFindDialog(this);
|
||||||
|
dialog->show();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionAbout_triggered()
|
void MainWindow::on_actionAbout_triggered()
|
||||||
{
|
{
|
||||||
AboutDialog *a = new AboutDialog(this);
|
AboutDialog *a = new AboutDialog(this);
|
||||||
@ -1759,7 +1771,7 @@ void MainWindow::on_actionExport_as_code_triggered()
|
|||||||
|
|
||||||
QFile file(dialog.selectedFiles()[0]);
|
QFile file(dialog.selectedFiles()[0]);
|
||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||||
qWarning() << "Can't open file";
|
qWarning() << tr("Can't open file");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1774,8 +1786,6 @@ void MainWindow::on_actionExport_as_code_triggered()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
auto string = fromOwned(
|
auto string = fromOwned(
|
||||||
dialog.selectedNameFilter() != instructionsInComments
|
dialog.selectedNameFilter() != instructionsInComments
|
||||||
? rz_lang_byte_array(buffer.data(), size, typMap[dialog.selectedNameFilter()])
|
? rz_lang_byte_array(buffer.data(), size, typMap[dialog.selectedNameFilter()])
|
||||||
|
@ -26,6 +26,7 @@ class FunctionsWidget;
|
|||||||
class ImportsWidget;
|
class ImportsWidget;
|
||||||
class ExportsWidget;
|
class ExportsWidget;
|
||||||
class SymbolsWidget;
|
class SymbolsWidget;
|
||||||
|
class GlobalsWidget;
|
||||||
class RelocsWidget;
|
class RelocsWidget;
|
||||||
class CommentsWidget;
|
class CommentsWidget;
|
||||||
class StringsWidget;
|
class StringsWidget;
|
||||||
@ -152,6 +153,7 @@ public slots:
|
|||||||
|
|
||||||
void toggleOverview(bool visibility, GraphWidget *targetGraph);
|
void toggleOverview(bool visibility, GraphWidget *targetGraph);
|
||||||
private slots:
|
private slots:
|
||||||
|
void on_actionBaseFind_triggered();
|
||||||
void on_actionAbout_triggered();
|
void on_actionAbout_triggered();
|
||||||
void on_actionIssue_triggered();
|
void on_actionIssue_triggered();
|
||||||
void documentationClicked();
|
void documentationClicked();
|
||||||
@ -239,6 +241,7 @@ private:
|
|||||||
TypesWidget *typesDock = nullptr;
|
TypesWidget *typesDock = nullptr;
|
||||||
SearchWidget *searchDock = nullptr;
|
SearchWidget *searchDock = nullptr;
|
||||||
SymbolsWidget *symbolsDock = nullptr;
|
SymbolsWidget *symbolsDock = nullptr;
|
||||||
|
GlobalsWidget *globalsDock = nullptr;
|
||||||
RelocsWidget *relocsDock = nullptr;
|
RelocsWidget *relocsDock = nullptr;
|
||||||
CommentsWidget *commentsDock = nullptr;
|
CommentsWidget *commentsDock = nullptr;
|
||||||
StringsWidget *stringsDock = nullptr;
|
StringsWidget *stringsDock = nullptr;
|
||||||
|
@ -128,6 +128,12 @@
|
|||||||
<addaction name="actionSaveLayout"/>
|
<addaction name="actionSaveLayout"/>
|
||||||
<addaction name="menuLayouts"/>
|
<addaction name="menuLayouts"/>
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuTools">
|
||||||
|
<property name="title">
|
||||||
|
<string>Tools</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionBaseFind"/>
|
||||||
|
</widget>
|
||||||
<widget class="QMenu" name="menuHelp">
|
<widget class="QMenu" name="menuHelp">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Help</string>
|
<string>Help</string>
|
||||||
@ -184,6 +190,7 @@
|
|||||||
<addaction name="menuView"/>
|
<addaction name="menuView"/>
|
||||||
<addaction name="menuWindows"/>
|
<addaction name="menuWindows"/>
|
||||||
<addaction name="menuDebug"/>
|
<addaction name="menuDebug"/>
|
||||||
|
<addaction name="menuTools"/>
|
||||||
<addaction name="menuHelp"/>
|
<addaction name="menuHelp"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QToolBar" name="mainToolBar">
|
<widget class="QToolBar" name="mainToolBar">
|
||||||
@ -233,6 +240,11 @@
|
|||||||
<string>Zen mode</string>
|
<string>Zen mode</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionBaseFind">
|
||||||
|
<property name="text">
|
||||||
|
<string>BaseFind</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
<action name="actionAbout">
|
<action name="actionAbout">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>About</string>
|
<string>About</string>
|
||||||
|
@ -1,2 +1 @@
|
|||||||
#include "RizinCpp.h"
|
#include "RizinCpp.h"
|
||||||
|
|
||||||
|
@ -46,8 +46,7 @@ static inline auto fromOwned(RZ_OWN RzPVector *data)
|
|||||||
return { data, {} };
|
return { data, {} };
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline auto fromOwned(RZ_OWN RzList *data)
|
static inline auto fromOwned(RZ_OWN RzList *data) -> UniquePtrCP<decltype(data), &rz_list_free>
|
||||||
-> UniquePtrCP<decltype(data), &rz_list_free>
|
|
||||||
{
|
{
|
||||||
return { data, {} };
|
return { data, {} };
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include "CommentsDialog.h"
|
#include "CommentsDialog.h"
|
||||||
#include "ui_CommentsDialog.h"
|
#include "ui_CommentsDialog.h"
|
||||||
|
|
||||||
|
#include <QErrorMessage>
|
||||||
|
|
||||||
#include "core/Cutter.h"
|
#include "core/Cutter.h"
|
||||||
|
|
||||||
CommentsDialog::CommentsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::CommentsDialog)
|
CommentsDialog::CommentsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::CommentsDialog)
|
||||||
|
@ -49,8 +49,7 @@ void GlibcHeapBinsDialog::setChainInfo(int index)
|
|||||||
RzHeapChunkListItem *item;
|
RzHeapChunkListItem *item;
|
||||||
RzList *chunks = binsModel->getChunks(index);
|
RzList *chunks = binsModel->getChunks(index);
|
||||||
QString chainInfo;
|
QString chainInfo;
|
||||||
CutterRzListForeach(chunks, iter, RzHeapChunkListItem, item)
|
CutterRzListForeach (chunks, iter, RzHeapChunkListItem, item) {
|
||||||
{
|
|
||||||
chainInfo += " → " + RzAddressString(item->addr);
|
chainInfo += " → " + RzAddressString(item->addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
71
src/dialogs/GlobalVariableDialog.cpp
Normal file
71
src/dialogs/GlobalVariableDialog.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include "GlobalVariableDialog.h"
|
||||||
|
#include "ui_GlobalVariableDialog.h"
|
||||||
|
|
||||||
|
#include <QIntValidator>
|
||||||
|
#include "core/Cutter.h"
|
||||||
|
|
||||||
|
GlobalVariableDialog::GlobalVariableDialog(RVA offset, QWidget *parent)
|
||||||
|
: QDialog(parent),
|
||||||
|
ui(new Ui::GlobalVariableDialog),
|
||||||
|
offset(offset),
|
||||||
|
globalVariableName(""),
|
||||||
|
globalVariableOffset(RVA_INVALID)
|
||||||
|
{
|
||||||
|
// Setup UI
|
||||||
|
ui->setupUi(this);
|
||||||
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
|
RzAnalysisVarGlobal *globalVariable =
|
||||||
|
rz_analysis_var_global_get_byaddr_at(Core()->core()->analysis, offset);
|
||||||
|
if (globalVariable) {
|
||||||
|
globalVariableName = QString(globalVariable->name);
|
||||||
|
globalVariableOffset = globalVariable->addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalVariable) {
|
||||||
|
ui->nameEdit->setText(globalVariable->name);
|
||||||
|
QString globalVarType = Core()->getGlobalVariableType(globalVariable->name);
|
||||||
|
ui->typeEdit->setText(globalVarType);
|
||||||
|
ui->labelAction->setText(tr("Edit global variable at %1").arg(RzAddressString(offset)));
|
||||||
|
} else {
|
||||||
|
ui->labelAction->setText(tr("Add global variable at %1").arg(RzAddressString(offset)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect slots
|
||||||
|
connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
|
||||||
|
&GlobalVariableDialog::buttonBoxAccepted);
|
||||||
|
connect(ui->buttonBox, &QDialogButtonBox::rejected, this,
|
||||||
|
&GlobalVariableDialog::buttonBoxRejected);
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalVariableDialog::~GlobalVariableDialog() {}
|
||||||
|
|
||||||
|
void GlobalVariableDialog::buttonBoxAccepted()
|
||||||
|
{
|
||||||
|
QString name = ui->nameEdit->text();
|
||||||
|
QString typ = ui->typeEdit->text();
|
||||||
|
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
if (globalVariableOffset != RVA_INVALID) {
|
||||||
|
// Empty name and global variable exists -> delete the global variable
|
||||||
|
Core()->delGlobalVariable(globalVariableOffset);
|
||||||
|
} else {
|
||||||
|
// GlobalVariable was not existing and we gave an empty name, do nothing
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (globalVariableOffset != RVA_INVALID) {
|
||||||
|
// Name provided and global variable exists -> rename the global variable
|
||||||
|
Core()->modifyGlobalVariable(globalVariableOffset, name, typ);
|
||||||
|
} else {
|
||||||
|
// Name provided and global variable does not exist -> create the global variable
|
||||||
|
Core()->addGlobalVariable(offset, name, typ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
this->setResult(QDialog::Accepted);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalVariableDialog::buttonBoxRejected()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
this->setResult(QDialog::Rejected);
|
||||||
|
}
|
32
src/dialogs/GlobalVariableDialog.h
Normal file
32
src/dialogs/GlobalVariableDialog.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef GLOBALVARIABLEDIALOG_H
|
||||||
|
#define GLOBALVARIABLEDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <memory>
|
||||||
|
#include "core/CutterCommon.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class GlobalVariableDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class GlobalVariableDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GlobalVariableDialog(RVA offset, QWidget *parent = nullptr);
|
||||||
|
~GlobalVariableDialog();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void buttonBoxAccepted();
|
||||||
|
void buttonBoxRejected();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::GlobalVariableDialog> ui;
|
||||||
|
RVA offset;
|
||||||
|
QString globalVariableName;
|
||||||
|
RVA globalVariableOffset;
|
||||||
|
QString typ;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GLOBALVARIABLEDIALOG_H
|
100
src/dialogs/GlobalVariableDialog.ui
Normal file
100
src/dialogs/GlobalVariableDialog.ui
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>GlobalVariableDialog</class>
|
||||||
|
<widget class="QDialog" name="GlobalVariableDialog">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>452</width>
|
||||||
|
<height>121</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Add Global Variable</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="labelAction">
|
||||||
|
<property name="text">
|
||||||
|
<string>Add global variable at</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<property name="horizontalSpacing">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="labelName">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Name:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QLineEdit" name="nameEdit">
|
||||||
|
<property name="frame">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="typeEdit">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>100</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>int</string>
|
||||||
|
</property>
|
||||||
|
<property name="frame">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string notr="true"/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="labelType">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<weight>75</weight>
|
||||||
|
<bold>true</bold>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "core/Cutter.h"
|
#include "core/Cutter.h"
|
||||||
#include "common/AnalysisTask.h"
|
#include "common/AnalysisTask.h"
|
||||||
|
#include "CutterApplication.h"
|
||||||
|
|
||||||
InitialOptionsDialog::InitialOptionsDialog(MainWindow *main)
|
InitialOptionsDialog::InitialOptionsDialog(MainWindow *main)
|
||||||
: QDialog(nullptr), // parent must not be main
|
: QDialog(nullptr), // parent must not be main
|
||||||
@ -179,9 +180,56 @@ void InitialOptionsDialog::loadOptions(const InitialOptions &options)
|
|||||||
ui->entry_loadOffset->setText(RzAddressString(options.binLoadAddr));
|
ui->entry_loadOffset->setText(RzAddressString(options.binLoadAddr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.mapAddr != RVA_INVALID) {
|
||||||
|
ui->entry_mapOffset->setText(RzAddressString(options.mapAddr));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->vaCheckBox->setChecked(options.useVA);
|
||||||
ui->writeCheckBox->setChecked(options.writeEnabled);
|
ui->writeCheckBox->setChecked(options.writeEnabled);
|
||||||
|
|
||||||
// TODO: all other options should also be applied to the ui
|
if (!options.arch.isNull() && !options.arch.isEmpty()) {
|
||||||
|
ui->archComboBox->setCurrentText(options.arch);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.cpu.isNull() && !options.cpu.isEmpty()) {
|
||||||
|
ui->cpuComboBox->setCurrentText(options.cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.bits > 0) {
|
||||||
|
ui->bitsComboBox->setCurrentText(QString::asprintf("%d", options.bits));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.os.isNull() && !options.os.isEmpty()) {
|
||||||
|
ui->kernelComboBox->setCurrentText(options.os);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.forceBinPlugin.isNull() && !options.forceBinPlugin.isEmpty()) {
|
||||||
|
ui->formatComboBox->setCurrentText(options.forceBinPlugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.loadBinInfo) {
|
||||||
|
ui->binCheckBox->setChecked(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->writeCheckBox->setChecked(options.writeEnabled);
|
||||||
|
|
||||||
|
switch (options.endian) {
|
||||||
|
case InitialOptions::Endianness::Little:
|
||||||
|
ui->endiannessComboBox->setCurrentIndex(1);
|
||||||
|
break;
|
||||||
|
case InitialOptions::Endianness::Big:
|
||||||
|
ui->endiannessComboBox->setCurrentIndex(2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->demangleCheckBox->setChecked(options.demangle);
|
||||||
|
|
||||||
|
if (!options.pdbFile.isNull() && !options.pdbFile.isEmpty()) {
|
||||||
|
ui->pdbCheckBox->setChecked(true);
|
||||||
|
ui->pdbLineEdit->setText(options.pdbFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialOptionsDialog::setTooltipWithConfigHelp(QWidget *w, const char *config)
|
void InitialOptionsDialog::setTooltipWithConfigHelp(QWidget *w, const char *config)
|
||||||
@ -246,7 +294,7 @@ QList<CommandDescription> InitialOptionsDialog::getSelectedAdvancedAnalCmds() co
|
|||||||
return advanced;
|
return advanced;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialOptionsDialog::setupAndStartAnalysis(/*int level, QList<QString> advanced*/)
|
void InitialOptionsDialog::setupAndStartAnalysis()
|
||||||
{
|
{
|
||||||
InitialOptions options;
|
InitialOptions options;
|
||||||
|
|
||||||
@ -322,6 +370,8 @@ void InitialOptionsDialog::setupAndStartAnalysis(/*int level, QList<QString> adv
|
|||||||
Core()->getAsyncTaskManager()->start(analysisTaskPtr);
|
Core()->getAsyncTaskManager()->start(analysisTaskPtr);
|
||||||
|
|
||||||
done(0);
|
done(0);
|
||||||
|
|
||||||
|
static_cast<CutterApplication *>(qApp)->setInitialOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitialOptionsDialog::on_okButton_clicked()
|
void InitialOptionsDialog::on_okButton_clicked()
|
||||||
|
@ -20,7 +20,7 @@ public:
|
|||||||
explicit InitialOptionsDialog(MainWindow *main);
|
explicit InitialOptionsDialog(MainWindow *main);
|
||||||
~InitialOptionsDialog();
|
~InitialOptionsDialog();
|
||||||
|
|
||||||
void setupAndStartAnalysis(/*int level, QList<QString> advanced*/);
|
void setupAndStartAnalysis();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_okButton_clicked();
|
void on_okButton_clicked();
|
||||||
|
@ -287,7 +287,8 @@ void NewFileDialog::fillIOPluginsList()
|
|||||||
{
|
{
|
||||||
ui->ioPlugin->clear();
|
ui->ioPlugin->clear();
|
||||||
ui->ioPlugin->addItem("file://");
|
ui->ioPlugin->addItem("file://");
|
||||||
ui->ioPlugin->setItemData(0, tr("Open a file without additional options/settings."), Qt::ToolTipRole);
|
ui->ioPlugin->setItemData(0, tr("Open a file without additional options/settings."),
|
||||||
|
Qt::ToolTipRole);
|
||||||
|
|
||||||
int index = 1;
|
int index = 1;
|
||||||
QList<RzIOPluginDescription> ioPlugins = Core()->getRIOPluginDescriptions();
|
QList<RzIOPluginDescription> ioPlugins = Core()->getRIOPluginDescriptions();
|
||||||
|
@ -70,8 +70,10 @@ void TypesInteractionDialog::done(int r)
|
|||||||
ui->plainTextEdit->toPlainText().toUtf8().constData());
|
ui->plainTextEdit->toPlainText().toUtf8().constData());
|
||||||
} else {
|
} else {
|
||||||
char *error_msg = NULL;
|
char *error_msg = NULL;
|
||||||
success = rz_type_parse_string_stateless(core->analysis->typedb->parser,
|
success = rz_type_parse_string_stateless(
|
||||||
ui->plainTextEdit->toPlainText().toUtf8().constData(), &error_msg) == 0;
|
core->analysis->typedb->parser,
|
||||||
|
ui->plainTextEdit->toPlainText().toUtf8().constData(), &error_msg)
|
||||||
|
== 0;
|
||||||
if (error_msg) {
|
if (error_msg) {
|
||||||
RZ_LOG_ERROR("%s\n", error_msg);
|
RZ_LOG_ERROR("%s\n", error_msg);
|
||||||
rz_mem_free(error_msg);
|
rz_mem_free(error_msg);
|
||||||
|
@ -65,6 +65,12 @@ AsmOptionsWidget::AsmOptionsWidget(PreferencesDialog *dialog)
|
|||||||
&AsmOptionsWidget::relOffCheckBoxToggled);
|
&AsmOptionsWidget::relOffCheckBoxToggled);
|
||||||
connect(Core(), &CutterCore::asmOptionsChanged, this,
|
connect(Core(), &CutterCore::asmOptionsChanged, this,
|
||||||
&AsmOptionsWidget::updateAsmOptionsFromVars);
|
&AsmOptionsWidget::updateAsmOptionsFromVars);
|
||||||
|
|
||||||
|
connect(ui->varTooltipsCheckBox, &QCheckBox::toggled, [this](bool checked) {
|
||||||
|
Config()->setShowVarTooltips(checked);
|
||||||
|
triggerAsmOptionsChanged();
|
||||||
|
});
|
||||||
|
|
||||||
updateAsmOptionsFromVars();
|
updateAsmOptionsFromVars();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +144,8 @@ void AsmOptionsWidget::updateAsmOptionsFromVars()
|
|||||||
ui->previewCheckBox->setChecked(Config()->getPreviewValue());
|
ui->previewCheckBox->setChecked(Config()->getPreviewValue());
|
||||||
ui->previewCheckBox->blockSignals(false);
|
ui->previewCheckBox->blockSignals(false);
|
||||||
|
|
||||||
|
qhelpers::setCheckedWithoutSignals(ui->varTooltipsCheckBox, Config()->getShowVarTooltips());
|
||||||
|
|
||||||
QList<ConfigCheckbox>::iterator confCheckbox;
|
QList<ConfigCheckbox>::iterator confCheckbox;
|
||||||
|
|
||||||
// Set the value for each checkbox in "checkboxes" as it exists in the configuration
|
// Set the value for each checkbox in "checkboxes" as it exists in the configuration
|
||||||
|
@ -48,8 +48,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>582</width>
|
<width>686</width>
|
||||||
<height>766</height>
|
<height>886</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
@ -65,51 +65,114 @@
|
|||||||
<string>Disassembly</string>
|
<string>Disassembly</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="12" column="2">
|
<item row="5" column="2">
|
||||||
<widget class="QSpinBox" name="nbytesSpinBox">
|
<widget class="QComboBox" name="caseComboBox">
|
||||||
<property name="enabled">
|
<item>
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="17" column="2">
|
|
||||||
<widget class="QSpinBox" name="asmTabsOffSpinBox">
|
|
||||||
<property name="maximum">
|
|
||||||
<number>100</number>
|
|
||||||
</property>
|
|
||||||
<property name="singleStep">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="19" column="1" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="lbytesCheckBox">
|
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Align bytes to the left (asm.lbytes)</string>
|
<string>Lowercase</string>
|
||||||
</property>
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Uppercase (asm.ucase)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Capitalize (asm.capitalize)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="15" column="1">
|
<item row="17" column="1">
|
||||||
<widget class="QCheckBox" name="previewCheckBox">
|
<widget class="QLabel" name="asmTabsLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show preview when hovering:</string>
|
<string>Tabs in assembly (asm.tabs):</string>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="1">
|
|
||||||
<widget class="QLabel" name="syntaxLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Syntax (asm.syntax):</string>
|
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="8" column="2">
|
<item row="11" column="1">
|
||||||
<widget class="QCheckBox" name="relOffFlagsCheckBox">
|
<widget class="QCheckBox" name="bytesCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Flags (asm.reloff.flags)</string>
|
<string>Display the bytes of each instruction (asm.bytes)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show Disassembly as:</string>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1" colspan="2">
|
||||||
|
<spacer name="verticalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::Fixed</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>10</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="13" column="1">
|
||||||
|
<widget class="QCheckBox" name="realnameCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Display flags' real name (asm.flags.real)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="8" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="relOffsetLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show offsets relative to:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="relOffsetCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Functions (asm.reloff)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="18" column="1">
|
||||||
|
<widget class="QLabel" name="asmTabsOffLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>The number of tabulate spaces after the offset (asm.tabs.off):</string>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="19" column="1" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="indentCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Indent disassembly based on reflines depth (asm.indent)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="7" column="1">
|
||||||
|
<widget class="QCheckBox" name="offsetCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show offsets (asm.offset)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -132,23 +195,47 @@
|
|||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="1">
|
<item row="14" column="1" colspan="2">
|
||||||
<widget class="QCheckBox" name="offsetCheckBox">
|
<widget class="QCheckBox" name="bblineCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show offsets (asm.offset)</string>
|
<string>Show empty line after every basic block (asm.bb.line)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="17" column="1">
|
<item row="15" column="1">
|
||||||
<widget class="QLabel" name="asmTabsOffLabel">
|
<widget class="QCheckBox" name="previewCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>The number of tabulate spaces after the offset (asm.tabs.off):</string>
|
<string>Show preview when hovering</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLabel" name="syntaxLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Syntax (asm.syntax):</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="textInteractionFlags">
|
<property name="textInteractionFlags">
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="21" column="1" colspan="2">
|
||||||
|
<widget class="QCheckBox" name="bytespaceCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Separate bytes with whitespace (asm.bytes.space)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="18" column="2">
|
||||||
|
<widget class="QSpinBox" name="asmTabsOffSpinBox">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>5</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="12" column="1">
|
<item row="12" column="1">
|
||||||
<widget class="QLabel" name="nbytesLabel">
|
<widget class="QLabel" name="nbytesLabel">
|
||||||
<property name="enabled">
|
<property name="enabled">
|
||||||
@ -163,13 +250,13 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="20" column="1" colspan="2">
|
<item row="20" column="1" colspan="2">
|
||||||
<widget class="QCheckBox" name="bytespaceCheckBox">
|
<widget class="QCheckBox" name="lbytesCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Separate bytes with whitespace (asm.bytes.space)</string>
|
<string>Align bytes to the left (asm.lbytes)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="16" column="2">
|
<item row="17" column="2">
|
||||||
<widget class="QSpinBox" name="asmTabsSpinBox">
|
<widget class="QSpinBox" name="asmTabsSpinBox">
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>100</number>
|
<number>100</number>
|
||||||
@ -179,107 +266,27 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="11" column="1">
|
<item row="8" column="2">
|
||||||
<widget class="QCheckBox" name="bytesCheckBox">
|
<widget class="QCheckBox" name="relOffFlagsCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Display the bytes of each instruction (asm.bytes)</string>
|
<string>Flags (asm.reloff.flags)</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="2">
|
|
||||||
<widget class="QComboBox" name="caseComboBox">
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Lowercase</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Uppercase (asm.ucase)</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Capitalize (asm.capitalize)</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="14" column="1" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="bblineCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Show empty line after every basic block (asm.bb.line)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="8" column="1">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="relOffsetLabel">
|
|
||||||
<property name="text">
|
|
||||||
<string>Show offsets relative to:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="relOffsetCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Functions (asm.reloff)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="2">
|
<item row="4" column="2">
|
||||||
<widget class="QComboBox" name="syntaxComboBox"/>
|
<widget class="QComboBox" name="syntaxComboBox"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1" colspan="2">
|
<item row="12" column="2">
|
||||||
<spacer name="verticalSpacer_3">
|
<widget class="QSpinBox" name="nbytesSpinBox">
|
||||||
<property name="orientation">
|
<property name="enabled">
|
||||||
<enum>Qt::Vertical</enum>
|
<bool>true</bool>
|
||||||
</property>
|
|
||||||
<property name="sizeType">
|
|
||||||
<enum>QSizePolicy::Fixed</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>10</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item row="3" column="1">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Show Disassembly as:</string>
|
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="16" column="1">
|
<item row="16" column="1">
|
||||||
<widget class="QLabel" name="asmTabsLabel">
|
<widget class="QCheckBox" name="varTooltipsCheckBox">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Tabs in assembly (asm.tabs):</string>
|
<string>Show known variable values when hovering</string>
|
||||||
</property>
|
|
||||||
<property name="textInteractionFlags">
|
|
||||||
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="18" column="1" colspan="2">
|
|
||||||
<widget class="QCheckBox" name="indentCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Indent disassembly based on reflines depth (asm.indent)</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="13" column="1">
|
|
||||||
<widget class="QCheckBox" name="realnameCheckBox">
|
|
||||||
<property name="text">
|
|
||||||
<string>Display flags' real name (asm.flags.real)</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -415,8 +422,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>454</width>
|
<width>518</width>
|
||||||
<height>286</height>
|
<height>326</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||||
|
@ -112,7 +112,8 @@ void AddressableItemContextMenu::aboutToShowSlot()
|
|||||||
void AddressableItemContextMenu::setHasTarget(bool hasTarget)
|
void AddressableItemContextMenu::setHasTarget(bool hasTarget)
|
||||||
{
|
{
|
||||||
this->hasTarget = hasTarget;
|
this->hasTarget = hasTarget;
|
||||||
for (const auto &action : this->actions()) {
|
actionShowInMenu->setEnabled(hasTarget);
|
||||||
action->setEnabled(hasTarget);
|
actionCopyAddress->setEnabled(hasTarget);
|
||||||
}
|
actionShowXrefs->setEnabled(hasTarget);
|
||||||
|
actionAddcomment->setEnabled(hasTarget);
|
||||||
}
|
}
|
||||||
|
@ -387,7 +387,7 @@ void DecompilerContextMenu::actionCopyReferenceAddressTriggered()
|
|||||||
|
|
||||||
void DecompilerContextMenu::actionAddCommentTriggered()
|
void DecompilerContextMenu::actionAddCommentTriggered()
|
||||||
{
|
{
|
||||||
CommentsDialog::addOrEditComment(this->firstOffsetInLine, this);
|
CommentsDialog::addOrEditComment(this->firstOffsetInLine, parentForDialog());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompilerContextMenu::actionDeleteCommentTriggered()
|
void DecompilerContextMenu::actionDeleteCommentTriggered()
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include "dialogs/EditInstructionDialog.h"
|
#include "dialogs/EditInstructionDialog.h"
|
||||||
#include "dialogs/CommentsDialog.h"
|
#include "dialogs/CommentsDialog.h"
|
||||||
#include "dialogs/FlagDialog.h"
|
#include "dialogs/FlagDialog.h"
|
||||||
|
#include "dialogs/GlobalVariableDialog.h"
|
||||||
#include "dialogs/XrefsDialog.h"
|
#include "dialogs/XrefsDialog.h"
|
||||||
#include "dialogs/EditVariablesDialog.h"
|
#include "dialogs/EditVariablesDialog.h"
|
||||||
#include "dialogs/SetToDataDialog.h"
|
#include "dialogs/SetToDataDialog.h"
|
||||||
@ -34,6 +35,7 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow *main
|
|||||||
actionAnalyzeFunction(this),
|
actionAnalyzeFunction(this),
|
||||||
actionEditFunction(this),
|
actionEditFunction(this),
|
||||||
actionRename(this),
|
actionRename(this),
|
||||||
|
actionGlobalVar(this),
|
||||||
actionSetFunctionVarTypes(this),
|
actionSetFunctionVarTypes(this),
|
||||||
actionXRefs(this),
|
actionXRefs(this),
|
||||||
actionXRefsForVariables(this),
|
actionXRefsForVariables(this),
|
||||||
@ -83,10 +85,6 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow *main
|
|||||||
getCommentSequence());
|
getCommentSequence());
|
||||||
addAction(&actionAddComment);
|
addAction(&actionAddComment);
|
||||||
|
|
||||||
initAction(&actionRename, tr("Rename or add flag"), SLOT(on_actionRename_triggered()),
|
|
||||||
getRenameSequence());
|
|
||||||
addAction(&actionRename);
|
|
||||||
|
|
||||||
initAction(&actionSetFunctionVarTypes, tr("Re-type Local Variables"),
|
initAction(&actionSetFunctionVarTypes, tr("Re-type Local Variables"),
|
||||||
SLOT(on_actionSetFunctionVarTypes_triggered()), getRetypeSequence());
|
SLOT(on_actionSetFunctionVarTypes_triggered()), getRetypeSequence());
|
||||||
addAction(&actionSetFunctionVarTypes);
|
addAction(&actionSetFunctionVarTypes);
|
||||||
@ -112,6 +110,8 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow *main
|
|||||||
|
|
||||||
addSeparator();
|
addSeparator();
|
||||||
|
|
||||||
|
addAddAtMenu();
|
||||||
|
|
||||||
addSetBaseMenu();
|
addSetBaseMenu();
|
||||||
|
|
||||||
addSetBitsMenu();
|
addSetBitsMenu();
|
||||||
@ -161,6 +161,24 @@ DisassemblyContextMenu::DisassemblyContextMenu(QWidget *parent, MainWindow *main
|
|||||||
|
|
||||||
DisassemblyContextMenu::~DisassemblyContextMenu() {}
|
DisassemblyContextMenu::~DisassemblyContextMenu() {}
|
||||||
|
|
||||||
|
QWidget *DisassemblyContextMenu::parentForDialog()
|
||||||
|
{
|
||||||
|
return parentWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisassemblyContextMenu::addAddAtMenu()
|
||||||
|
{
|
||||||
|
setAsMenu = addMenu(tr("Add at..."));
|
||||||
|
|
||||||
|
initAction(&actionRename, tr("Rename or add flag"), SLOT(on_actionRename_triggered()),
|
||||||
|
getRenameSequence());
|
||||||
|
setAsMenu->addAction(&actionRename);
|
||||||
|
|
||||||
|
initAction(&actionGlobalVar, tr("Modify or add global variable"),
|
||||||
|
SLOT(on_actionGlobalVar_triggered()), getGlobalVarSequence());
|
||||||
|
setAsMenu->addAction(&actionGlobalVar);
|
||||||
|
}
|
||||||
|
|
||||||
void DisassemblyContextMenu::addSetBaseMenu()
|
void DisassemblyContextMenu::addSetBaseMenu()
|
||||||
{
|
{
|
||||||
setBaseMenu = addMenu(tr("Set base of immediate value to.."));
|
setBaseMenu = addMenu(tr("Set base of immediate value to.."));
|
||||||
@ -314,8 +332,7 @@ void DisassemblyContextMenu::addDebugMenu()
|
|||||||
QVector<DisassemblyContextMenu::ThingUsedHere> DisassemblyContextMenu::getThingUsedHere(RVA offset)
|
QVector<DisassemblyContextMenu::ThingUsedHere> DisassemblyContextMenu::getThingUsedHere(RVA offset)
|
||||||
{
|
{
|
||||||
RzCoreLocked core(Core());
|
RzCoreLocked core(Core());
|
||||||
auto p = fromOwned(
|
auto p = fromOwned(rz_core_analysis_name(core, offset), rz_core_analysis_name_free);
|
||||||
rz_core_analysis_name(core, offset), rz_core_analysis_name_free);
|
|
||||||
if (!p) {
|
if (!p) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@ -475,7 +492,12 @@ void DisassemblyContextMenu::setupRenaming()
|
|||||||
|
|
||||||
// Now, build the renaming menu and show it
|
// Now, build the renaming menu and show it
|
||||||
buildRenameMenu(tuh);
|
buildRenameMenu(tuh);
|
||||||
|
|
||||||
|
auto name = RzAddressString(tuh->offset);
|
||||||
|
actionGlobalVar.setText(tr("Add or change global variable at %1 (used here)").arg(name));
|
||||||
|
|
||||||
actionRename.setVisible(true);
|
actionRename.setVisible(true);
|
||||||
|
actionGlobalVar.setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassemblyContextMenu::aboutToShowSlot()
|
void DisassemblyContextMenu::aboutToShowSlot()
|
||||||
@ -651,6 +673,11 @@ QKeySequence DisassemblyContextMenu::getRenameSequence() const
|
|||||||
return { Qt::Key_N };
|
return { Qt::Key_N };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QKeySequence DisassemblyContextMenu::getGlobalVarSequence() const
|
||||||
|
{
|
||||||
|
return { Qt::Key_G };
|
||||||
|
}
|
||||||
|
|
||||||
QKeySequence DisassemblyContextMenu::getRetypeSequence() const
|
QKeySequence DisassemblyContextMenu::getRetypeSequence() const
|
||||||
{
|
{
|
||||||
return { Qt::Key_Y };
|
return { Qt::Key_Y };
|
||||||
@ -691,7 +718,7 @@ void DisassemblyContextMenu::on_actionEditInstruction_triggered()
|
|||||||
if (!ioModesController.prepareForWriting()) {
|
if (!ioModesController.prepareForWriting()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EditInstructionDialog e(EDIT_TEXT, this);
|
EditInstructionDialog e(EDIT_TEXT, parentForDialog());
|
||||||
e.setWindowTitle(tr("Edit Instruction at %1").arg(RzAddressString(offset)));
|
e.setWindowTitle(tr("Edit Instruction at %1").arg(RzAddressString(offset)));
|
||||||
|
|
||||||
QString oldInstructionOpcode = Core()->getInstructionOpcode(offset);
|
QString oldInstructionOpcode = Core()->getInstructionOpcode(offset);
|
||||||
@ -741,7 +768,7 @@ void DisassemblyContextMenu::on_actionEditBytes_triggered()
|
|||||||
if (!ioModesController.prepareForWriting()) {
|
if (!ioModesController.prepareForWriting()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EditInstructionDialog e(EDIT_BYTES, this);
|
EditInstructionDialog e(EDIT_BYTES, parentForDialog());
|
||||||
e.setWindowTitle(tr("Edit Bytes at %1").arg(RzAddressString(offset)));
|
e.setWindowTitle(tr("Edit Bytes at %1").arg(RzAddressString(offset)));
|
||||||
|
|
||||||
QString oldBytes = Core()->getInstructionBytes(offset);
|
QString oldBytes = Core()->getInstructionBytes(offset);
|
||||||
@ -775,9 +802,9 @@ void DisassemblyContextMenu::on_actionAdvancedBreakpoint_triggered()
|
|||||||
{
|
{
|
||||||
int index = Core()->breakpointIndexAt(offset);
|
int index = Core()->breakpointIndexAt(offset);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
BreakpointsDialog::editBreakpoint(Core()->getBreakpointAt(offset), this);
|
BreakpointsDialog::editBreakpoint(Core()->getBreakpointAt(offset), parentForDialog());
|
||||||
} else {
|
} else {
|
||||||
BreakpointsDialog::createNewBreakpoint(offset, this);
|
BreakpointsDialog::createNewBreakpoint(offset, parentForDialog());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -794,12 +821,11 @@ void DisassemblyContextMenu::on_actionSetPC_triggered()
|
|||||||
|
|
||||||
void DisassemblyContextMenu::on_actionAddComment_triggered()
|
void DisassemblyContextMenu::on_actionAddComment_triggered()
|
||||||
{
|
{
|
||||||
CommentsDialog::addOrEditComment(offset, this);
|
CommentsDialog::addOrEditComment(offset, parentForDialog());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassemblyContextMenu::on_actionAnalyzeFunction_triggered()
|
void DisassemblyContextMenu::on_actionAnalyzeFunction_triggered()
|
||||||
{
|
{
|
||||||
bool ok;
|
|
||||||
RVA flagOffset;
|
RVA flagOffset;
|
||||||
QString name = Core()->nearestFlag(offset, &flagOffset);
|
QString name = Core()->nearestFlag(offset, &flagOffset);
|
||||||
if (name.isEmpty() || flagOffset != offset) {
|
if (name.isEmpty() || flagOffset != offset) {
|
||||||
@ -812,12 +838,20 @@ void DisassemblyContextMenu::on_actionAnalyzeFunction_triggered()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create dialog
|
// Create dialog
|
||||||
QString functionName =
|
QInputDialog inputDialog(parentForDialog());
|
||||||
QInputDialog::getText(this, tr("New function at %1").arg(RzAddressString(offset)),
|
inputDialog.resize(500, 100);
|
||||||
tr("Function name:"), QLineEdit::Normal, name, &ok);
|
inputDialog.setWindowTitle(tr("New function at %1").arg(RzAddressString(offset)));
|
||||||
|
inputDialog.setLabelText(tr("Function name:"));
|
||||||
|
inputDialog.setTextValue(name);
|
||||||
|
inputDialog.setWindowFlags(Qt::Window | Qt::WindowMinimizeButtonHint);
|
||||||
|
|
||||||
// If user accepted
|
if (inputDialog.exec() != QDialog::Accepted) {
|
||||||
if (ok && !functionName.isEmpty()) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString functionName = inputDialog.textValue().trimmed();
|
||||||
|
|
||||||
|
if (!functionName.isEmpty()) {
|
||||||
Core()->createFunctionAt(offset, functionName);
|
Core()->createFunctionAt(offset, functionName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -833,12 +867,12 @@ void DisassemblyContextMenu::on_actionRename_triggered()
|
|||||||
Core()->renameFunction(doRenameInfo.addr, newName);
|
Core()->renameFunction(doRenameInfo.addr, newName);
|
||||||
}
|
}
|
||||||
} else if (doRenameAction == RENAME_FLAG || doRenameAction == RENAME_ADD_FLAG) {
|
} else if (doRenameAction == RENAME_FLAG || doRenameAction == RENAME_ADD_FLAG) {
|
||||||
FlagDialog dialog(doRenameInfo.addr, this->mainWindow);
|
FlagDialog dialog(doRenameInfo.addr, parentForDialog());
|
||||||
ok = dialog.exec();
|
ok = dialog.exec();
|
||||||
} else if (doRenameAction == RENAME_LOCAL) {
|
} else if (doRenameAction == RENAME_LOCAL) {
|
||||||
RzAnalysisFunction *fcn = Core()->functionIn(offset);
|
RzAnalysisFunction *fcn = Core()->functionIn(offset);
|
||||||
if (fcn) {
|
if (fcn) {
|
||||||
EditVariablesDialog dialog(fcn->addr, curHighlightedWord, this->mainWindow);
|
EditVariablesDialog dialog(fcn->addr, curHighlightedWord, parentForDialog());
|
||||||
if (!dialog.empty()) {
|
if (!dialog.empty()) {
|
||||||
// Don't show the dialog if there are no variables
|
// Don't show the dialog if there are no variables
|
||||||
ok = dialog.exec();
|
ok = dialog.exec();
|
||||||
@ -857,6 +891,18 @@ void DisassemblyContextMenu::on_actionRename_triggered()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DisassemblyContextMenu::on_actionGlobalVar_triggered()
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
GlobalVariableDialog dialog(doRenameInfo.addr, parentForDialog());
|
||||||
|
ok = dialog.exec();
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
// Rebuild menu in case the user presses the rename shortcut directly before clicking
|
||||||
|
setupRenaming();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DisassemblyContextMenu::on_actionSetFunctionVarTypes_triggered()
|
void DisassemblyContextMenu::on_actionSetFunctionVarTypes_triggered()
|
||||||
{
|
{
|
||||||
RzAnalysisFunction *fcn = Core()->functionIn(offset);
|
RzAnalysisFunction *fcn = Core()->functionIn(offset);
|
||||||
@ -867,7 +913,7 @@ void DisassemblyContextMenu::on_actionSetFunctionVarTypes_triggered()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
EditVariablesDialog dialog(fcn->addr, curHighlightedWord, this->mainWindow);
|
EditVariablesDialog dialog(fcn->addr, curHighlightedWord, parentForDialog());
|
||||||
if (dialog.empty()) { // don't show the dialog if there are no variables
|
if (dialog.empty()) { // don't show the dialog if there are no variables
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -892,7 +938,7 @@ void DisassemblyContextMenu::on_actionXRefsForVariables_triggered()
|
|||||||
|
|
||||||
void DisassemblyContextMenu::on_actionDisplayOptions_triggered()
|
void DisassemblyContextMenu::on_actionDisplayOptions_triggered()
|
||||||
{
|
{
|
||||||
PreferencesDialog dialog(this->window());
|
PreferencesDialog dialog(parentForDialog());
|
||||||
dialog.showSection(PreferencesDialog::Section::Disassembly);
|
dialog.showSection(PreferencesDialog::Section::Disassembly);
|
||||||
dialog.exec();
|
dialog.exec();
|
||||||
}
|
}
|
||||||
@ -914,7 +960,7 @@ void DisassemblyContextMenu::on_actionSetAsStringRemove_triggered()
|
|||||||
|
|
||||||
void DisassemblyContextMenu::on_actionSetAsStringAdvanced_triggered()
|
void DisassemblyContextMenu::on_actionSetAsStringAdvanced_triggered()
|
||||||
{
|
{
|
||||||
EditStringDialog dialog(parentWidget());
|
EditStringDialog dialog(parentForDialog());
|
||||||
const int predictedStrSize = Core()->getString(offset).size();
|
const int predictedStrSize = Core()->getString(offset).size();
|
||||||
dialog.setStringSizeValue(predictedStrSize);
|
dialog.setStringSizeValue(predictedStrSize);
|
||||||
dialog.setStringStartAddress(offset);
|
dialog.setStringStartAddress(offset);
|
||||||
@ -964,7 +1010,7 @@ void DisassemblyContextMenu::on_actionSetToData_triggered()
|
|||||||
|
|
||||||
void DisassemblyContextMenu::on_actionSetToDataEx_triggered()
|
void DisassemblyContextMenu::on_actionSetToDataEx_triggered()
|
||||||
{
|
{
|
||||||
SetToDataDialog dialog(offset, this->window());
|
SetToDataDialog dialog(offset, parentForDialog());
|
||||||
if (!dialog.exec()) {
|
if (!dialog.exec()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -994,7 +1040,7 @@ void DisassemblyContextMenu::on_actionDeleteFunction_triggered()
|
|||||||
void DisassemblyContextMenu::on_actionEditFunction_triggered()
|
void DisassemblyContextMenu::on_actionEditFunction_triggered()
|
||||||
{
|
{
|
||||||
RzCore *core = Core()->core();
|
RzCore *core = Core()->core();
|
||||||
EditFunctionDialog dialog(mainWindow);
|
EditFunctionDialog dialog(parentForDialog());
|
||||||
RzAnalysisFunction *fcn = rz_analysis_get_fcn_in(core->analysis, offset, 0);
|
RzAnalysisFunction *fcn = rz_analysis_get_fcn_in(core->analysis, offset, 0);
|
||||||
|
|
||||||
if (fcn) {
|
if (fcn) {
|
||||||
|
@ -45,6 +45,7 @@ private slots:
|
|||||||
void on_actionAddComment_triggered();
|
void on_actionAddComment_triggered();
|
||||||
void on_actionAnalyzeFunction_triggered();
|
void on_actionAnalyzeFunction_triggered();
|
||||||
void on_actionRename_triggered();
|
void on_actionRename_triggered();
|
||||||
|
void on_actionGlobalVar_triggered();
|
||||||
void on_actionSetFunctionVarTypes_triggered();
|
void on_actionSetFunctionVarTypes_triggered();
|
||||||
void on_actionXRefs_triggered();
|
void on_actionXRefs_triggered();
|
||||||
void on_actionXRefsForVariables_triggered();
|
void on_actionXRefsForVariables_triggered();
|
||||||
@ -78,6 +79,7 @@ private:
|
|||||||
QKeySequence getCopySequence() const;
|
QKeySequence getCopySequence() const;
|
||||||
QKeySequence getCommentSequence() const;
|
QKeySequence getCommentSequence() const;
|
||||||
QKeySequence getCopyAddressSequence() const;
|
QKeySequence getCopyAddressSequence() const;
|
||||||
|
QKeySequence getGlobalVarSequence() const;
|
||||||
QKeySequence getSetToCodeSequence() const;
|
QKeySequence getSetToCodeSequence() const;
|
||||||
QKeySequence getSetAsStringSequence() const;
|
QKeySequence getSetAsStringSequence() const;
|
||||||
QKeySequence getSetAsStringAdvanced() const;
|
QKeySequence getSetAsStringAdvanced() const;
|
||||||
@ -114,6 +116,7 @@ private:
|
|||||||
QAction actionAnalyzeFunction;
|
QAction actionAnalyzeFunction;
|
||||||
QAction actionEditFunction;
|
QAction actionEditFunction;
|
||||||
QAction actionRename;
|
QAction actionRename;
|
||||||
|
QAction actionGlobalVar;
|
||||||
QAction actionSetFunctionVarTypes;
|
QAction actionSetFunctionVarTypes;
|
||||||
QAction actionXRefs;
|
QAction actionXRefs;
|
||||||
QAction actionXRefsForVariables;
|
QAction actionXRefsForVariables;
|
||||||
@ -168,6 +171,11 @@ private:
|
|||||||
QMenu *pluginMenu = nullptr;
|
QMenu *pluginMenu = nullptr;
|
||||||
QAction *pluginActionMenuAction = nullptr;
|
QAction *pluginActionMenuAction = nullptr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \return widget that should be used as parent for presenting dialogs
|
||||||
|
*/
|
||||||
|
QWidget *parentForDialog();
|
||||||
|
|
||||||
// For creating anonymous entries (that are always visible)
|
// For creating anonymous entries (that are always visible)
|
||||||
QAction *addAnonymousAction(QString name, const char *slot, QKeySequence shortcut);
|
QAction *addAnonymousAction(QString name, const char *slot, QKeySequence shortcut);
|
||||||
|
|
||||||
@ -185,6 +193,7 @@ private:
|
|||||||
void addSetAsMenu();
|
void addSetAsMenu();
|
||||||
void addSetToDataMenu();
|
void addSetToDataMenu();
|
||||||
void addEditMenu();
|
void addEditMenu();
|
||||||
|
void addAddAtMenu();
|
||||||
void addBreakpointMenu();
|
void addBreakpointMenu();
|
||||||
void addDebugMenu();
|
void addDebugMenu();
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
<update_contact>xarkes</update_contact>
|
<update_contact>xarkes</update_contact>
|
||||||
|
|
||||||
<releases>
|
<releases>
|
||||||
<release version="2.2.1" date="2023-05-15" />
|
|
||||||
<release version="2.2.0" date="2023-02-22" />
|
<release version="2.2.0" date="2023-02-22" />
|
||||||
<release version="2.1.2" date="2022-09-11" />
|
<release version="2.1.2" date="2022-09-11" />
|
||||||
<release version="2.1.1" date="2022-09-10" />
|
<release version="2.1.1" date="2022-09-10" />
|
||||||
|
97
src/tools/basefind/BaseFindDialog.cpp
Normal file
97
src/tools/basefind/BaseFindDialog.cpp
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
#include "BaseFindDialog.h"
|
||||||
|
#include "ui_BaseFindDialog.h"
|
||||||
|
|
||||||
|
#include "BaseFindSearchDialog.h"
|
||||||
|
|
||||||
|
#include <core/Cutter.h>
|
||||||
|
#include <rz_th.h>
|
||||||
|
|
||||||
|
BaseFindDialog::BaseFindDialog(QWidget *parent) : QDialog(parent), ui(new Ui::BaseFindDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
|
|
||||||
|
// Fill in N-thread Combo
|
||||||
|
size_t n_cores = rz_th_physical_core_number();
|
||||||
|
ui->nCoresCombo->clear();
|
||||||
|
for (size_t i = n_cores; i > 0; i--) {
|
||||||
|
if (n_cores == i) {
|
||||||
|
ui->nCoresCombo->addItem("All Cores");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ui->nCoresCombo->addItem(QString::number(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->startAddressEdit->setText(Core()->getConfig("basefind.search.start"));
|
||||||
|
ui->endAddressEdit->setText(Core()->getConfig("basefind.search.end"));
|
||||||
|
ui->alignmentEdit->setText(Core()->getConfig("basefind.alignment"));
|
||||||
|
ui->minStrLenEdit->setValue(Core()->getConfigut64("basefind.min.string"));
|
||||||
|
ui->minScoreEdit->setValue(Core()->getConfigut64("basefind.min.score"));
|
||||||
|
|
||||||
|
size_t selected_n_cores = Core()->getConfigut64("basefind.max.threads");
|
||||||
|
if (selected_n_cores < n_cores && selected_n_cores > 0) {
|
||||||
|
ui->nCoresCombo->setCurrentIndex(n_cores - selected_n_cores);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseFindDialog::~BaseFindDialog() {}
|
||||||
|
|
||||||
|
size_t BaseFindDialog::getNCores() const
|
||||||
|
{
|
||||||
|
size_t n_cores = rz_th_physical_core_number();
|
||||||
|
return n_cores - ui->nCoresCombo->currentIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
ut32 BaseFindDialog::getPointerSize() const
|
||||||
|
{
|
||||||
|
auto index = ui->pointerSizeCombo->currentIndex();
|
||||||
|
QString value = ui->pointerSizeCombo->itemText(index);
|
||||||
|
return value.toULong(nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
RVA BaseFindDialog::getStartAddress() const
|
||||||
|
{
|
||||||
|
QString value = ui->startAddressEdit->text();
|
||||||
|
return value.toULongLong(nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
RVA BaseFindDialog::getEndAddress() const
|
||||||
|
{
|
||||||
|
QString value = ui->endAddressEdit->text();
|
||||||
|
return value.toULongLong(nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
RVA BaseFindDialog::getAlignment() const
|
||||||
|
{
|
||||||
|
QString value = ui->alignmentEdit->text();
|
||||||
|
return value.toULongLong(nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ut32 BaseFindDialog::getMinStrLen() const
|
||||||
|
{
|
||||||
|
return ui->minStrLenEdit->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
ut32 BaseFindDialog::getMinScore() const
|
||||||
|
{
|
||||||
|
return ui->minScoreEdit->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseFindDialog::on_buttonBox_accepted()
|
||||||
|
{
|
||||||
|
RzBaseFindOpt options = {};
|
||||||
|
options.max_threads = getNCores();
|
||||||
|
options.pointer_size = getPointerSize();
|
||||||
|
options.start_address = getStartAddress();
|
||||||
|
options.end_address = getEndAddress();
|
||||||
|
options.alignment = getAlignment();
|
||||||
|
options.min_score = getMinScore();
|
||||||
|
options.min_string_len = getMinStrLen();
|
||||||
|
options.callback = nullptr;
|
||||||
|
options.user = nullptr;
|
||||||
|
|
||||||
|
BaseFindSearchDialog *bfs = new BaseFindSearchDialog(parentWidget());
|
||||||
|
bfs->show(&options);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseFindDialog::on_buttonBox_rejected() {}
|
38
src/tools/basefind/BaseFindDialog.h
Normal file
38
src/tools/basefind/BaseFindDialog.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#ifndef BASEFIND_DIALOG_H
|
||||||
|
#define BASEFIND_DIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QListWidgetItem>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <core/Cutter.h>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class BaseFindDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BaseFindDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BaseFindDialog(QWidget *parent = nullptr);
|
||||||
|
~BaseFindDialog();
|
||||||
|
|
||||||
|
size_t getNCores() const;
|
||||||
|
ut32 getPointerSize() const;
|
||||||
|
RVA getStartAddress() const;
|
||||||
|
RVA getEndAddress() const;
|
||||||
|
RVA getAlignment() const;
|
||||||
|
ut32 getMinStrLen() const;
|
||||||
|
ut32 getMinScore() const;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_buttonBox_accepted();
|
||||||
|
void on_buttonBox_rejected();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::BaseFindDialog> ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BASEFIND_DIALOG_H
|
246
src/tools/basefind/BaseFindDialog.ui
Normal file
246
src/tools/basefind/BaseFindDialog.ui
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>BaseFindDialog</class>
|
||||||
|
<widget class="QDialog" name="BaseFindDialog">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::NonModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>373</width>
|
||||||
|
<height>348</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true">BaseFind</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="nCoresLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Cores:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QComboBox" name="nCoresCombo"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="pointerSizeLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Pointer Size:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QComboBox" name="pointerSizeCombo">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>32</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>64</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="startAddressLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Start Address:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="startAddressEdit">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>382</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="endAddressLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>End Address:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QLineEdit" name="endAddressEdit">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>382</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="alignmentLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Alignment:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<widget class="QLineEdit" name="alignmentEdit">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>382</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="minStrLenLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Min String Length:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QSpinBox" name="minStrLenEdit">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>382</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>4</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="0">
|
||||||
|
<widget class="QLabel" name="minScoreLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Min Score:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="6" column="1">
|
||||||
|
<widget class="QSpinBox" name="minScoreEdit">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>382</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>999999999</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
<action name="actionRemoveItem">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove item</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionRemoveAll">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove all</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Remove all</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>BaseFindDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>234</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>BaseFindDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>240</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
161
src/tools/basefind/BaseFindResultsDialog.cpp
Normal file
161
src/tools/basefind/BaseFindResultsDialog.cpp
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
#include "BaseFindResultsDialog.h"
|
||||||
|
#include "ui_BaseFindResultsDialog.h"
|
||||||
|
|
||||||
|
#include <QClipboard>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
#include <core/Cutter.h>
|
||||||
|
#include <CutterApplication.h>
|
||||||
|
|
||||||
|
BaseFindResultsModel::BaseFindResultsModel(QList<BasefindResultDescription> *list, QObject *parent)
|
||||||
|
: QAbstractListModel(parent), list(list)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseFindResultsModel::rowCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return list->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int BaseFindResultsModel::columnCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return BaseFindResultsModel::ColumnCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant BaseFindResultsModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (index.row() >= list->count())
|
||||||
|
return QVariant();
|
||||||
|
|
||||||
|
const BasefindResultDescription &entry = list->at(index.row());
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (index.column()) {
|
||||||
|
case ScoreColumn:
|
||||||
|
return QString::asprintf("%u", entry.score);
|
||||||
|
case CandidateColumn:
|
||||||
|
return QString::asprintf("%#010llx", entry.candidate);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
case Qt::ToolTipRole: {
|
||||||
|
return QString::asprintf("%#010llx", entry.candidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant BaseFindResultsModel::headerData(int section, Qt::Orientation, int role) const
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (section) {
|
||||||
|
case ScoreColumn:
|
||||||
|
return tr("Score");
|
||||||
|
case CandidateColumn:
|
||||||
|
return tr("Address");
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseFindResultsDialog::BaseFindResultsDialog(QList<BasefindResultDescription> results,
|
||||||
|
QWidget *parent)
|
||||||
|
: QDialog(parent), list(results), ui(new Ui::BaseFindResultsDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
|
|
||||||
|
model = new BaseFindResultsModel(&list, this);
|
||||||
|
ui->tableView->setModel(model);
|
||||||
|
ui->tableView->sortByColumn(BaseFindResultsModel::ScoreColumn, Qt::AscendingOrder);
|
||||||
|
ui->tableView->verticalHeader()->hide();
|
||||||
|
ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||||
|
ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
|
||||||
|
blockMenu = new QMenu(this);
|
||||||
|
actionCopyCandidate = new QAction(tr("Copy %1"), this);
|
||||||
|
actionSetLoadAddr = new QAction(tr("Reopen Cutter with base address as %1"), this);
|
||||||
|
actionSetMapAddr = new QAction(tr("Reopen Cutter with map address as %1"), this);
|
||||||
|
|
||||||
|
connect(ui->tableView, &QWidget::customContextMenuRequested, this,
|
||||||
|
&BaseFindResultsDialog::showItemContextMenu);
|
||||||
|
connect(actionCopyCandidate, &QAction::triggered, this,
|
||||||
|
&BaseFindResultsDialog::onActionCopyLine);
|
||||||
|
connect(actionSetLoadAddr, &QAction::triggered, this,
|
||||||
|
&BaseFindResultsDialog::onActionSetLoadAddr);
|
||||||
|
connect(actionSetMapAddr, &QAction::triggered, this,
|
||||||
|
&BaseFindResultsDialog::onActionSetMapAddr);
|
||||||
|
|
||||||
|
blockMenu->addAction(actionSetLoadAddr);
|
||||||
|
blockMenu->addAction(actionSetMapAddr);
|
||||||
|
blockMenu->addAction(actionCopyCandidate);
|
||||||
|
addActions(blockMenu->actions());
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseFindResultsDialog::showItemContextMenu(const QPoint &pt)
|
||||||
|
{
|
||||||
|
auto index = ui->tableView->currentIndex();
|
||||||
|
if (index.isValid()) {
|
||||||
|
const BasefindResultDescription &entry = list.at(index.row());
|
||||||
|
candidate = entry.candidate;
|
||||||
|
auto addr = QString::asprintf("%#010llx", candidate);
|
||||||
|
actionCopyCandidate->setText(tr("Copy %1").arg(addr));
|
||||||
|
actionSetLoadAddr->setText(tr("Reopen Cutter with base address as %1").arg(addr));
|
||||||
|
actionSetMapAddr->setText(tr("Reopen Cutter with map address as %1").arg(addr));
|
||||||
|
blockMenu->exec(this->mapToGlobal(pt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseFindResultsDialog::onActionCopyLine()
|
||||||
|
{
|
||||||
|
auto clipboard = QApplication::clipboard();
|
||||||
|
clipboard->setText(QString::asprintf("%#010llx", candidate));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseFindResultsDialog::onActionSetLoadAddr()
|
||||||
|
{
|
||||||
|
auto cutter = static_cast<CutterApplication *>(qApp);
|
||||||
|
auto options = cutter->getInitialOptions();
|
||||||
|
auto oldValue = options.binLoadAddr;
|
||||||
|
|
||||||
|
// override options to generate correct args
|
||||||
|
options.binLoadAddr = candidate;
|
||||||
|
cutter->setInitialOptions(options);
|
||||||
|
auto args = cutter->getArgs();
|
||||||
|
|
||||||
|
// revert back options
|
||||||
|
options.binLoadAddr = oldValue;
|
||||||
|
cutter->setInitialOptions(options);
|
||||||
|
|
||||||
|
cutter->launchNewInstance(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseFindResultsDialog::onActionSetMapAddr()
|
||||||
|
{
|
||||||
|
auto cutter = static_cast<CutterApplication *>(qApp);
|
||||||
|
auto options = cutter->getInitialOptions();
|
||||||
|
auto oldValue = options.mapAddr;
|
||||||
|
|
||||||
|
// override options to generate correct args
|
||||||
|
options.mapAddr = candidate;
|
||||||
|
cutter->setInitialOptions(options);
|
||||||
|
auto args = cutter->getArgs();
|
||||||
|
|
||||||
|
// revert back options
|
||||||
|
options.mapAddr = oldValue;
|
||||||
|
cutter->setInitialOptions(options);
|
||||||
|
|
||||||
|
cutter->launchNewInstance(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseFindResultsDialog::~BaseFindResultsDialog() {}
|
||||||
|
|
||||||
|
void BaseFindResultsDialog::on_buttonBox_rejected() {}
|
68
src/tools/basefind/BaseFindResultsDialog.h
Normal file
68
src/tools/basefind/BaseFindResultsDialog.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#ifndef BASEFIND_RESULTS_DIALOG_H
|
||||||
|
#define BASEFIND_RESULTS_DIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <core/Cutter.h>
|
||||||
|
|
||||||
|
class BaseFindResultsDialog;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class BaseFindResultsDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BaseFindResultsModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend BaseFindResultsDialog;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Column { ScoreColumn = 0, CandidateColumn, ColumnCount };
|
||||||
|
|
||||||
|
BaseFindResultsModel(QList<BasefindResultDescription> *list, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<BasefindResultDescription> *list;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BaseFindResultsDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BaseFindResultsDialog(QList<BasefindResultDescription> results,
|
||||||
|
QWidget *parent = nullptr);
|
||||||
|
~BaseFindResultsDialog();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void showItemContextMenu(const QPoint &pt);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_buttonBox_rejected();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onActionCopyLine();
|
||||||
|
void onActionSetLoadAddr();
|
||||||
|
void onActionSetMapAddr();
|
||||||
|
|
||||||
|
QList<BasefindResultDescription> list;
|
||||||
|
std::unique_ptr<Ui::BaseFindResultsDialog> ui;
|
||||||
|
BaseFindResultsModel *model;
|
||||||
|
QMenu *blockMenu;
|
||||||
|
QAction *actionCopyCandidate;
|
||||||
|
QAction *actionSetLoadAddr;
|
||||||
|
QAction *actionSetMapAddr;
|
||||||
|
RVA candidate;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BASEFIND_RESULTS_DIALOG_H
|
70
src/tools/basefind/BaseFindResultsDialog.ui
Normal file
70
src/tools/basefind/BaseFindResultsDialog.ui
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>BaseFindResultsDialog</class>
|
||||||
|
<widget class="QDialog" name="BaseFindResultsDialog">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::NonModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>582</width>
|
||||||
|
<height>382</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true">BaseFind Results</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="mainVerticalLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QTableView" name="tableView"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Close</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>BaseFindResultsDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>240</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
66
src/tools/basefind/BaseFindSearchDialog.cpp
Normal file
66
src/tools/basefind/BaseFindSearchDialog.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include "BaseFindSearchDialog.h"
|
||||||
|
#include "ui_BaseFindSearchDialog.h"
|
||||||
|
|
||||||
|
#include "BaseFindResultsDialog.h"
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QFormLayout>
|
||||||
|
|
||||||
|
#include <core/Cutter.h>
|
||||||
|
#include <rz_th.h>
|
||||||
|
|
||||||
|
BaseFindSearchDialog::BaseFindSearchDialog(QWidget *parent)
|
||||||
|
: QDialog(parent), basefind(new Basefind(Core())), ui(new Ui::BaseFindSearchDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
|
||||||
|
}
|
||||||
|
|
||||||
|
BaseFindSearchDialog::~BaseFindSearchDialog() {}
|
||||||
|
|
||||||
|
void BaseFindSearchDialog::show(RzBaseFindOpt *opts)
|
||||||
|
{
|
||||||
|
size_t n_cores = rz_th_physical_core_number();
|
||||||
|
if (opts->max_threads > n_cores || opts->max_threads < 1) {
|
||||||
|
opts->max_threads = n_cores;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFormLayout *layout = new QFormLayout();
|
||||||
|
ui->scrollAreaWidgetContents->setLayout(layout);
|
||||||
|
for (ut32 i = 0; i < opts->max_threads; ++i) {
|
||||||
|
QString label = QString::asprintf("Core %u", i);
|
||||||
|
QProgressBar *pbar = new QProgressBar(nullptr);
|
||||||
|
layout->addRow(label, pbar);
|
||||||
|
pbar->setRange(0, 100);
|
||||||
|
bars.push_back(pbar);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!basefind->setOptions(opts)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(this, &BaseFindSearchDialog::cancelSearch, basefind.get(), &Basefind::cancel);
|
||||||
|
connect(basefind.get(), &Basefind::progress, this, &BaseFindSearchDialog::onProgress);
|
||||||
|
connect(basefind.get(), &Basefind::complete, this, &BaseFindSearchDialog::onCompletion);
|
||||||
|
|
||||||
|
basefind->start();
|
||||||
|
this->QDialog::show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseFindSearchDialog::onProgress(BasefindCoreStatusDescription status)
|
||||||
|
{
|
||||||
|
bars[status.index]->setValue(status.percentage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseFindSearchDialog::onCompletion()
|
||||||
|
{
|
||||||
|
auto results = basefind->results();
|
||||||
|
BaseFindResultsDialog *table = new BaseFindResultsDialog(results, parentWidget());
|
||||||
|
table->show();
|
||||||
|
this->close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseFindSearchDialog::on_buttonBox_rejected()
|
||||||
|
{
|
||||||
|
emit cancelSearch();
|
||||||
|
}
|
41
src/tools/basefind/BaseFindSearchDialog.h
Normal file
41
src/tools/basefind/BaseFindSearchDialog.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#ifndef BASEFIND_SEARCH_DIALOG_H
|
||||||
|
#define BASEFIND_SEARCH_DIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QListWidgetItem>
|
||||||
|
#include <QProgressBar>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <core/Cutter.h>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class BaseFindSearchDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BaseFindSearchDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BaseFindSearchDialog(QWidget *parent = nullptr);
|
||||||
|
~BaseFindSearchDialog();
|
||||||
|
|
||||||
|
void show(RzBaseFindOpt *opts);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void onProgress(BasefindCoreStatusDescription status);
|
||||||
|
void onCompletion();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void cancelSearch();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_buttonBox_rejected();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<QProgressBar *> bars;
|
||||||
|
std::unique_ptr<Basefind> basefind;
|
||||||
|
std::unique_ptr<Ui::BaseFindSearchDialog> ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BASEFIND_SEARCH_DIALOG_H
|
112
src/tools/basefind/BaseFindSearchDialog.ui
Normal file
112
src/tools/basefind/BaseFindSearchDialog.ui
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>BaseFindSearchDialog</class>
|
||||||
|
<widget class="QDialog" name="BaseFindSearchDialog">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::NonModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>582</width>
|
||||||
|
<height>382</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true">Searching for base address</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="mainVerticalLayout">
|
||||||
|
<property name="sizeConstraint">
|
||||||
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="sizeAdjustPolicy">
|
||||||
|
<enum>QAbstractScrollArea::AdjustToContents</enum>
|
||||||
|
</property>
|
||||||
|
<property name="widgetResizable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>564</width>
|
||||||
|
<height>320</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
<action name="actionRemoveItem">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove item</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionRemoveAll">
|
||||||
|
<property name="text">
|
||||||
|
<string>Remove all</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Remove all</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>BaseFindSearchDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>240</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
@ -1 +1 @@
|
|||||||
Subproject commit e8fc5ca1acd70fd82a2ac9ac02b0261e57703250
|
Subproject commit 53b42f0854479f36170356c13d5eec4be3182444
|
@ -57,16 +57,30 @@ public:
|
|||||||
itemContextMenu = menu;
|
itemContextMenu = menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is set to true, the context menu will also be shown if no item
|
||||||
|
* is currently selected.
|
||||||
|
*/
|
||||||
|
void setShowItemContextMenuWithoutAddress(bool val) { showItemContextMenuWithoutAddress = val; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void showItemContextMenu(const QPoint &pt)
|
virtual void showItemContextMenu(const QPoint &pt)
|
||||||
{
|
{
|
||||||
|
if (!itemContextMenu) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
auto index = this->currentIndex();
|
auto index = this->currentIndex();
|
||||||
if (index.isValid() && itemContextMenu) {
|
if (index.isValid()) {
|
||||||
auto offset = addressableModel->address(index);
|
auto offset = addressableModel->address(index);
|
||||||
auto name = addressableModel->name(index);
|
auto name = addressableModel->name(index);
|
||||||
itemContextMenu->setTarget(offset, name);
|
itemContextMenu->setTarget(offset, name);
|
||||||
itemContextMenu->exec(this->mapToGlobal(pt));
|
} else {
|
||||||
|
if (!showItemContextMenuWithoutAddress) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
itemContextMenu->clearTarget();
|
||||||
|
}
|
||||||
|
itemContextMenu->exec(this->mapToGlobal(pt));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void onItemActivated(const QModelIndex &index)
|
virtual void onItemActivated(const QModelIndex &index)
|
||||||
@ -90,6 +104,7 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool showItemContextMenuWithoutAddress = false;
|
||||||
AddressableItemModelI *addressableModel = nullptr;
|
AddressableItemModelI *addressableModel = nullptr;
|
||||||
AddressableItemContextMenu *itemContextMenu = nullptr;
|
AddressableItemContextMenu *itemContextMenu = nullptr;
|
||||||
MainWindow *mainWindow = nullptr;
|
MainWindow *mainWindow = nullptr;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "ClassesWidget.h"
|
#include "ClassesWidget.h"
|
||||||
#include "core/MainWindow.h"
|
#include "core/MainWindow.h"
|
||||||
#include "ui_ClassesWidget.h"
|
#include "ui_ListDockWidget.h"
|
||||||
#include "common/Helpers.h"
|
#include "common/Helpers.h"
|
||||||
#include "common/SvgIconEngine.h"
|
#include "common/SvgIconEngine.h"
|
||||||
#include "dialogs/EditMethodDialog.h"
|
#include "dialogs/EditMethodDialog.h"
|
||||||
@ -9,6 +9,8 @@
|
|||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
|
#include <QShortcut>
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
QVariant ClassesModel::headerData(int section, Qt::Orientation, int role) const
|
QVariant ClassesModel::headerData(int section, Qt::Orientation, int role) const
|
||||||
{
|
{
|
||||||
@ -33,6 +35,17 @@ QVariant ClassesModel::headerData(int section, Qt::Orientation, int role) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RVA ClassesModel::address(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
QVariant v = data(index, OffsetRole);
|
||||||
|
return v.isValid() ? v.toULongLong() : RVA_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ClassesModel::name(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
return data(index, NameRole).toString();
|
||||||
|
}
|
||||||
|
|
||||||
BinClassesModel::BinClassesModel(QObject *parent) : ClassesModel(parent) {}
|
BinClassesModel::BinClassesModel(QObject *parent) : ClassesModel(parent) {}
|
||||||
|
|
||||||
void BinClassesModel::setClasses(const QList<BinClassDescription> &classes)
|
void BinClassesModel::setClasses(const QList<BinClassDescription> &classes)
|
||||||
@ -526,12 +539,17 @@ QVariant AnalysisClassesModel::data(const QModelIndex &index, int role) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClassesSortFilterProxyModel::ClassesSortFilterProxyModel(QObject *parent)
|
ClassesSortFilterProxyModel::ClassesSortFilterProxyModel(QObject *parent)
|
||||||
: QSortFilterProxyModel(parent)
|
: AddressableFilterProxyModel(nullptr, parent)
|
||||||
{
|
{
|
||||||
|
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClassesSortFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
|
bool ClassesSortFilterProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
|
if (parent.isValid())
|
||||||
|
return true;
|
||||||
|
|
||||||
QModelIndex index = sourceModel()->index(row, 0, parent);
|
QModelIndex index = sourceModel()->index(row, 0, parent);
|
||||||
return qhelpers::filterStringContains(index.data(ClassesModel::NameRole).toString(), this);
|
return qhelpers::filterStringContains(index.data(ClassesModel::NameRole).toString(), this);
|
||||||
}
|
}
|
||||||
@ -576,23 +594,63 @@ bool ClassesSortFilterProxyModel::hasChildren(const QModelIndex &parent) const
|
|||||||
return !parent.isValid() || !parent.parent().isValid();
|
return !parent.isValid() || !parent.parent().isValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassesWidget::ClassesWidget(MainWindow *main) : CutterDockWidget(main), ui(new Ui::ClassesWidget)
|
ClassesWidget::ClassesWidget(MainWindow *main)
|
||||||
|
: ListDockWidget(main),
|
||||||
|
seekToVTableAction(tr("Seek to VTable"), this),
|
||||||
|
editMethodAction(tr("Edit Method"), this),
|
||||||
|
addMethodAction(tr("Add Method"), this),
|
||||||
|
newClassAction(tr("Create new Class"), this),
|
||||||
|
renameClassAction(tr("Rename Class"), this),
|
||||||
|
deleteClassAction(tr("Delete Class"), this)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
setWindowTitle(tr("Classes"));
|
||||||
|
setObjectName("ClassesWidget");
|
||||||
|
|
||||||
ui->classesTreeView->setIconSize(QSize(10, 10));
|
ui->treeView->setIconSize(QSize(10, 10));
|
||||||
|
|
||||||
proxy_model = new ClassesSortFilterProxyModel(this);
|
proxy_model = new ClassesSortFilterProxyModel(this);
|
||||||
ui->classesTreeView->setModel(proxy_model);
|
setModels(proxy_model);
|
||||||
ui->classesTreeView->sortByColumn(ClassesModel::TYPE, Qt::AscendingOrder);
|
|
||||||
ui->classesTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
||||||
|
|
||||||
ui->classSourceCombo->setCurrentIndex(1);
|
classSourceCombo = new QComboBox(this);
|
||||||
|
// User an intermediate single-child layout to contain the combo box, otherwise
|
||||||
|
// when the combo box is inserted directly, the entire vertical layout gets a
|
||||||
|
// weird horizontal padding on macOS.
|
||||||
|
QBoxLayout *comboLayout = new QBoxLayout(QBoxLayout::Direction::LeftToRight, nullptr);
|
||||||
|
comboLayout->addWidget(classSourceCombo);
|
||||||
|
ui->verticalLayout->insertLayout(ui->verticalLayout->indexOf(ui->quickFilterView), comboLayout);
|
||||||
|
classSourceCombo->addItem(tr("Binary Info (Fixed)"));
|
||||||
|
classSourceCombo->addItem(tr("Analysis (Editable)"));
|
||||||
|
classSourceCombo->setCurrentIndex(1);
|
||||||
|
|
||||||
connect<void (QComboBox::*)(int)>(ui->classSourceCombo, &QComboBox::currentIndexChanged, this,
|
connect<void (QComboBox::*)(int)>(classSourceCombo, &QComboBox::currentIndexChanged, this,
|
||||||
&ClassesWidget::refreshClasses);
|
&ClassesWidget::refreshClasses);
|
||||||
connect(ui->classesTreeView, &QTreeView::customContextMenuRequested, this,
|
|
||||||
&ClassesWidget::showContextMenu);
|
connect(&seekToVTableAction, &QAction::triggered, this,
|
||||||
|
&ClassesWidget::seekToVTableActionTriggered);
|
||||||
|
connect(&editMethodAction, &QAction::triggered, this,
|
||||||
|
&ClassesWidget::editMethodActionTriggered);
|
||||||
|
connect(&addMethodAction, &QAction::triggered, this, &ClassesWidget::addMethodActionTriggered);
|
||||||
|
connect(&newClassAction, &QAction::triggered, this, &ClassesWidget::newClassActionTriggered);
|
||||||
|
connect(&renameClassAction, &QAction::triggered, this,
|
||||||
|
&ClassesWidget::renameClassActionTriggered);
|
||||||
|
connect(&deleteClassAction, &QAction::triggered, this,
|
||||||
|
&ClassesWidget::deleteClassActionTriggered);
|
||||||
|
|
||||||
|
// Build context menu like this:
|
||||||
|
// class-related actions
|
||||||
|
// -- classesMethodsSeparator
|
||||||
|
// method-related actions
|
||||||
|
// -- separator
|
||||||
|
// default actions from AddressableItemList
|
||||||
|
auto contextMenu = ui->treeView->getItemContextMenu();
|
||||||
|
contextMenu->insertSeparator(contextMenu->actions().first());
|
||||||
|
contextMenu->insertActions(contextMenu->actions().first(),
|
||||||
|
{ &addMethodAction, &editMethodAction, &seekToVTableAction });
|
||||||
|
classesMethodsSeparator = contextMenu->insertSeparator(contextMenu->actions().first());
|
||||||
|
contextMenu->insertActions(classesMethodsSeparator,
|
||||||
|
{ &newClassAction, &renameClassAction, &deleteClassAction });
|
||||||
|
connect(contextMenu, &QMenu::aboutToShow, this, &ClassesWidget::updateActions);
|
||||||
|
ui->treeView->setShowItemContextMenuWithoutAddress(true);
|
||||||
|
|
||||||
refreshClasses();
|
refreshClasses();
|
||||||
}
|
}
|
||||||
@ -601,7 +659,7 @@ ClassesWidget::~ClassesWidget() {}
|
|||||||
|
|
||||||
ClassesWidget::Source ClassesWidget::getSource()
|
ClassesWidget::Source ClassesWidget::getSource()
|
||||||
{
|
{
|
||||||
switch (ui->classSourceCombo->currentIndex()) {
|
switch (classSourceCombo->currentIndex()) {
|
||||||
case 0:
|
case 0:
|
||||||
return Source::BIN;
|
return Source::BIN;
|
||||||
default:
|
default:
|
||||||
@ -614,88 +672,68 @@ void ClassesWidget::refreshClasses()
|
|||||||
switch (getSource()) {
|
switch (getSource()) {
|
||||||
case Source::BIN:
|
case Source::BIN:
|
||||||
if (!bin_model) {
|
if (!bin_model) {
|
||||||
proxy_model->setSourceModel(nullptr);
|
proxy_model->setSourceModel(static_cast<AddressableItemModelI *>(nullptr));
|
||||||
delete analysis_model;
|
delete analysis_model;
|
||||||
analysis_model = nullptr;
|
analysis_model = nullptr;
|
||||||
bin_model = new BinClassesModel(this);
|
bin_model = new BinClassesModel(this);
|
||||||
proxy_model->setSourceModel(bin_model);
|
proxy_model->setSourceModel(static_cast<AddressableItemModelI *>(bin_model));
|
||||||
}
|
}
|
||||||
bin_model->setClasses(Core()->getAllClassesFromBin());
|
bin_model->setClasses(Core()->getAllClassesFromBin());
|
||||||
break;
|
break;
|
||||||
case Source::ANALYSIS:
|
case Source::ANALYSIS:
|
||||||
if (!analysis_model) {
|
if (!analysis_model) {
|
||||||
proxy_model->setSourceModel(nullptr);
|
proxy_model->setSourceModel(static_cast<AddressableItemModelI *>(nullptr));
|
||||||
delete bin_model;
|
delete bin_model;
|
||||||
bin_model = nullptr;
|
bin_model = nullptr;
|
||||||
analysis_model = new AnalysisClassesModel(this);
|
analysis_model = new AnalysisClassesModel(this);
|
||||||
proxy_model->setSourceModel(analysis_model);
|
proxy_model->setSourceModel(static_cast<AddressableItemModelI *>(analysis_model));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
qhelpers::adjustColumns(ui->classesTreeView, 3, 0);
|
qhelpers::adjustColumns(ui->treeView, 3, 0);
|
||||||
|
|
||||||
ui->classesTreeView->setColumnWidth(0, 200);
|
ui->treeView->setColumnWidth(0, 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassesWidget::on_classesTreeView_doubleClicked(const QModelIndex &index)
|
void ClassesWidget::updateActions()
|
||||||
{
|
{
|
||||||
if (!index.isValid())
|
bool isAnalysis = !!analysis_model;
|
||||||
return;
|
newClassAction.setVisible(isAnalysis);
|
||||||
|
addMethodAction.setVisible(isAnalysis);
|
||||||
|
|
||||||
QVariant offsetData = index.data(ClassesModel::OffsetRole);
|
bool rowIsAnalysisClass = false;
|
||||||
if (!offsetData.isValid()) {
|
bool rowIsAnalysisMethod = false;
|
||||||
return;
|
QModelIndex index = ui->treeView->selectionModel()->currentIndex();
|
||||||
}
|
if (isAnalysis && index.isValid()) {
|
||||||
RVA offset = offsetData.value<RVA>();
|
|
||||||
Core()->seekAndShow(offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClassesWidget::showContextMenu(const QPoint &pt)
|
|
||||||
{
|
|
||||||
if (!analysis_model) {
|
|
||||||
// no context menu for bin classes
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex();
|
|
||||||
if (!index.isValid()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto type = static_cast<ClassesModel::RowType>(index.data(ClassesModel::TypeRole).toInt());
|
auto type = static_cast<ClassesModel::RowType>(index.data(ClassesModel::TypeRole).toInt());
|
||||||
|
rowIsAnalysisClass = type == ClassesModel::RowType::Class;
|
||||||
QMenu menu(ui->classesTreeView);
|
rowIsAnalysisMethod = type == ClassesModel::RowType::Method;
|
||||||
|
|
||||||
menu.addAction(ui->newClassAction);
|
|
||||||
|
|
||||||
if (type == ClassesModel::RowType::Class) {
|
|
||||||
menu.addAction(ui->renameClassAction);
|
|
||||||
menu.addAction(ui->deleteClassAction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.addSeparator();
|
renameClassAction.setVisible(rowIsAnalysisClass);
|
||||||
|
deleteClassAction.setVisible(rowIsAnalysisClass);
|
||||||
|
|
||||||
menu.addAction(ui->addMethodAction);
|
classesMethodsSeparator->setVisible(rowIsAnalysisClass || rowIsAnalysisMethod);
|
||||||
|
|
||||||
if (type == ClassesModel::RowType::Method) {
|
|
||||||
menu.addAction(ui->editMethodAction);
|
|
||||||
|
|
||||||
|
editMethodAction.setVisible(rowIsAnalysisMethod);
|
||||||
|
bool rowHasVTable = false;
|
||||||
|
if (rowIsAnalysisMethod) {
|
||||||
QString className = index.parent().data(ClassesModel::NameRole).toString();
|
QString className = index.parent().data(ClassesModel::NameRole).toString();
|
||||||
QString methodName = index.data(ClassesModel::NameRole).toString();
|
QString methodName = index.data(ClassesModel::NameRole).toString();
|
||||||
AnalysisMethodDescription desc;
|
AnalysisMethodDescription desc;
|
||||||
if (Core()->getAnalysisMethod(className, methodName, &desc)) {
|
if (Core()->getAnalysisMethod(className, methodName, &desc)) {
|
||||||
if (desc.vtableOffset >= 0) {
|
if (desc.vtableOffset >= 0) {
|
||||||
menu.addAction(ui->seekToVTableAction);
|
rowHasVTable = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
seekToVTableAction.setVisible(rowHasVTable);
|
||||||
|
}
|
||||||
|
|
||||||
menu.exec(ui->classesTreeView->mapToGlobal(pt));
|
void ClassesWidget::seekToVTableActionTriggered()
|
||||||
}
|
|
||||||
|
|
||||||
void ClassesWidget::on_seekToVTableAction_triggered()
|
|
||||||
{
|
{
|
||||||
QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex();
|
QModelIndex index = ui->treeView->selectionModel()->currentIndex();
|
||||||
QString className = index.parent().data(ClassesModel::NameRole).toString();
|
QString className = index.parent().data(ClassesModel::NameRole).toString();
|
||||||
|
|
||||||
QList<AnalysisVTableDescription> vtables = Core()->getAnalysisClassVTables(className);
|
QList<AnalysisVTableDescription> vtables = Core()->getAnalysisClassVTables(className);
|
||||||
@ -714,9 +752,9 @@ void ClassesWidget::on_seekToVTableAction_triggered()
|
|||||||
Core()->seekAndShow(vtables[0].addr + desc.vtableOffset);
|
Core()->seekAndShow(vtables[0].addr + desc.vtableOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassesWidget::on_addMethodAction_triggered()
|
void ClassesWidget::addMethodActionTriggered()
|
||||||
{
|
{
|
||||||
QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex();
|
QModelIndex index = ui->treeView->selectionModel()->currentIndex();
|
||||||
if (!index.isValid()) {
|
if (!index.isValid()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -732,9 +770,9 @@ void ClassesWidget::on_addMethodAction_triggered()
|
|||||||
EditMethodDialog::newMethod(className, QString(), this);
|
EditMethodDialog::newMethod(className, QString(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassesWidget::on_editMethodAction_triggered()
|
void ClassesWidget::editMethodActionTriggered()
|
||||||
{
|
{
|
||||||
QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex();
|
QModelIndex index = ui->treeView->selectionModel()->currentIndex();
|
||||||
if (!index.isValid()
|
if (!index.isValid()
|
||||||
|| index.data(ClassesModel::TypeRole).toInt()
|
|| index.data(ClassesModel::TypeRole).toInt()
|
||||||
!= static_cast<int>(ClassesModel::RowType::Method)) {
|
!= static_cast<int>(ClassesModel::RowType::Method)) {
|
||||||
@ -745,7 +783,7 @@ void ClassesWidget::on_editMethodAction_triggered()
|
|||||||
EditMethodDialog::editMethod(className, methName, this);
|
EditMethodDialog::editMethod(className, methName, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassesWidget::on_newClassAction_triggered()
|
void ClassesWidget::newClassActionTriggered()
|
||||||
{
|
{
|
||||||
bool ok;
|
bool ok;
|
||||||
QString name = QInputDialog::getText(this, tr("Create new Class"), tr("Class Name:"),
|
QString name = QInputDialog::getText(this, tr("Create new Class"), tr("Class Name:"),
|
||||||
@ -755,9 +793,9 @@ void ClassesWidget::on_newClassAction_triggered()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassesWidget::on_deleteClassAction_triggered()
|
void ClassesWidget::deleteClassActionTriggered()
|
||||||
{
|
{
|
||||||
QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex();
|
QModelIndex index = ui->treeView->selectionModel()->currentIndex();
|
||||||
if (!index.isValid()
|
if (!index.isValid()
|
||||||
|| index.data(ClassesModel::TypeRole).toInt()
|
|| index.data(ClassesModel::TypeRole).toInt()
|
||||||
!= static_cast<int>(ClassesModel::RowType::Class)) {
|
!= static_cast<int>(ClassesModel::RowType::Class)) {
|
||||||
@ -772,9 +810,9 @@ void ClassesWidget::on_deleteClassAction_triggered()
|
|||||||
Core()->deleteClass(className);
|
Core()->deleteClass(className);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassesWidget::on_renameClassAction_triggered()
|
void ClassesWidget::renameClassActionTriggered()
|
||||||
{
|
{
|
||||||
QModelIndex index = ui->classesTreeView->selectionModel()->currentIndex();
|
QModelIndex index = ui->treeView->selectionModel()->currentIndex();
|
||||||
if (!index.isValid()
|
if (!index.isValid()
|
||||||
|| index.data(ClassesModel::TypeRole).toInt()
|
|| index.data(ClassesModel::TypeRole).toInt()
|
||||||
!= static_cast<int>(ClassesModel::RowType::Class)) {
|
!= static_cast<int>(ClassesModel::RowType::Class)) {
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "core/Cutter.h"
|
#include "core/Cutter.h"
|
||||||
#include "CutterDockWidget.h"
|
#include "CutterDockWidget.h"
|
||||||
|
#include "widgets/ListDockWidget.h"
|
||||||
|
|
||||||
#include <QAbstractListModel>
|
#include <QAbstractListModel>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
@ -21,7 +22,7 @@ class ClassesWidget;
|
|||||||
/**
|
/**
|
||||||
* @brief Common abstract base class for Bin and Anal classes models
|
* @brief Common abstract base class for Bin and Anal classes models
|
||||||
*/
|
*/
|
||||||
class ClassesModel : public QAbstractItemModel
|
class ClassesModel : public AddressableItemModel<>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Columns { NAME = 0, REAL_NAME, TYPE, OFFSET, VTABLE, COUNT };
|
enum Columns { NAME = 0, REAL_NAME, TYPE, OFFSET, VTABLE, COUNT };
|
||||||
@ -69,10 +70,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
static const int RealNameRole = Qt::UserRole + 4;
|
static const int RealNameRole = Qt::UserRole + 4;
|
||||||
|
|
||||||
explicit ClassesModel(QObject *parent = nullptr) : QAbstractItemModel(parent) {}
|
explicit ClassesModel(QObject *parent = nullptr) : AddressableItemModel(parent) {}
|
||||||
|
|
||||||
QVariant headerData(int section, Qt::Orientation orientation,
|
QVariant headerData(int section, Qt::Orientation orientation,
|
||||||
int role = Qt::DisplayRole) const override;
|
int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
RVA address(const QModelIndex &index) const override;
|
||||||
|
QString name(const QModelIndex &index) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(ClassesModel::RowType)
|
Q_DECLARE_METATYPE(ClassesModel::RowType)
|
||||||
@ -163,7 +167,7 @@ public slots:
|
|||||||
void classAttrsChanged(const QString &cls);
|
void classAttrsChanged(const QString &cls);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClassesSortFilterProxyModel : public QSortFilterProxyModel
|
class ClassesSortFilterProxyModel : public AddressableFilterProxyModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -176,7 +180,7 @@ protected:
|
|||||||
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
|
bool hasChildren(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClassesWidget : public CutterDockWidget
|
class ClassesWidget : public ListDockWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@ -185,29 +189,34 @@ public:
|
|||||||
~ClassesWidget();
|
~ClassesWidget();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_classesTreeView_doubleClicked(const QModelIndex &index);
|
void seekToVTableActionTriggered();
|
||||||
|
void editMethodActionTriggered();
|
||||||
void on_seekToVTableAction_triggered();
|
void addMethodActionTriggered();
|
||||||
void on_addMethodAction_triggered();
|
void newClassActionTriggered();
|
||||||
void on_editMethodAction_triggered();
|
void renameClassActionTriggered();
|
||||||
void on_newClassAction_triggered();
|
void deleteClassActionTriggered();
|
||||||
void on_deleteClassAction_triggered();
|
|
||||||
void on_renameClassAction_triggered();
|
|
||||||
|
|
||||||
void showContextMenu(const QPoint &pt);
|
|
||||||
|
|
||||||
void refreshClasses();
|
void refreshClasses();
|
||||||
|
void updateActions();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class Source { BIN, ANALYSIS };
|
enum class Source { BIN, ANALYSIS };
|
||||||
|
|
||||||
Source getSource();
|
Source getSource();
|
||||||
|
|
||||||
std::unique_ptr<Ui::ClassesWidget> ui;
|
|
||||||
|
|
||||||
BinClassesModel *bin_model = nullptr;
|
BinClassesModel *bin_model = nullptr;
|
||||||
AnalysisClassesModel *analysis_model = nullptr;
|
AnalysisClassesModel *analysis_model = nullptr;
|
||||||
ClassesSortFilterProxyModel *proxy_model;
|
ClassesSortFilterProxyModel *proxy_model;
|
||||||
|
|
||||||
|
QComboBox *classSourceCombo;
|
||||||
|
|
||||||
|
QAction seekToVTableAction;
|
||||||
|
QAction editMethodAction;
|
||||||
|
QAction addMethodAction;
|
||||||
|
QAction newClassAction;
|
||||||
|
QAction renameClassAction;
|
||||||
|
QAction deleteClassAction;
|
||||||
|
QAction *classesMethodsSeparator;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CLASSESWIDGET_H
|
#endif // CLASSESWIDGET_H
|
||||||
|
@ -1,148 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>ClassesWidget</class>
|
|
||||||
<widget class="QDockWidget" name="ClassesWidget">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>400</width>
|
|
||||||
<height>300</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string notr="true">Classes</string>
|
|
||||||
</property>
|
|
||||||
<widget class="QWidget" name="dockWidgetContents">
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="CutterTreeView" name="classesTreeView">
|
|
||||||
<property name="styleSheet">
|
|
||||||
<string notr="true">CutterTreeView::item
|
|
||||||
{
|
|
||||||
padding-top: 1px;
|
|
||||||
padding-bottom: 1px;
|
|
||||||
}</string>
|
|
||||||
</property>
|
|
||||||
<property name="frameShape">
|
|
||||||
<enum>QFrame::NoFrame</enum>
|
|
||||||
</property>
|
|
||||||
<property name="lineWidth">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="sortingEnabled">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="expandsOnDoubleClick">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_17">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>10</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="classSourceLabel">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Source:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QComboBox" name="classSourceCombo">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Binary Info (Fixed)</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<property name="text">
|
|
||||||
<string>Analysis (Editable)</string>
|
|
||||||
</property>
|
|
||||||
</item>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<action name="seekToVTableAction">
|
|
||||||
<property name="text">
|
|
||||||
<string>Seek to VTable</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="editMethodAction">
|
|
||||||
<property name="text">
|
|
||||||
<string>Edit Method</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="addMethodAction">
|
|
||||||
<property name="text">
|
|
||||||
<string>Add Method</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="newClassAction">
|
|
||||||
<property name="text">
|
|
||||||
<string>Create new Class</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="renameClassAction">
|
|
||||||
<property name="text">
|
|
||||||
<string>Rename Class</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="deleteClassAction">
|
|
||||||
<property name="text">
|
|
||||||
<string>Delete Class</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
</widget>
|
|
||||||
<customwidgets>
|
|
||||||
<customwidget>
|
|
||||||
<class>CutterTreeView</class>
|
|
||||||
<extends>QTreeView</extends>
|
|
||||||
<header>widgets/CutterTreeView.h</header>
|
|
||||||
<container>1</container>
|
|
||||||
</customwidget>
|
|
||||||
</customwidgets>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
@ -22,8 +22,7 @@ void ColorThemeComboBox::updateFromConfig(bool interfaceThemeChanged)
|
|||||||
|
|
||||||
clear();
|
clear();
|
||||||
for (const QString &theme : themes) {
|
for (const QString &theme : themes) {
|
||||||
if (ThemeWorker().isCustomTheme(theme)
|
if (ThemeWorker().isCustomTheme(theme) || !Configuration::relevantThemes[theme]
|
||||||
|| !Configuration::relevantThemes[theme]
|
|
||||||
|| (Configuration::cutterInterfaceThemesList()[curInterfaceThemeIndex].flag
|
|| (Configuration::cutterInterfaceThemesList()[curInterfaceThemeIndex].flag
|
||||||
& Configuration::relevantThemes[theme])) {
|
& Configuration::relevantThemes[theme])) {
|
||||||
addItem(theme);
|
addItem(theme);
|
||||||
|
@ -128,8 +128,8 @@ void ColorOptionDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
|
|||||||
painter->setPen(qApp->palette().text().color());
|
painter->setPen(qApp->palette().text().color());
|
||||||
|
|
||||||
QFontMetrics fm2 = QFontMetrics(painter->font());
|
QFontMetrics fm2 = QFontMetrics(painter->font());
|
||||||
QString name = fm2.elidedText(optionInfoMap__[currCO.optionName].displayingtext,
|
QString name = fm2.elidedText(optionInfoMap__[currCO.optionName].displayingtext, Qt::ElideRight,
|
||||||
Qt::ElideRight, optionNameRect.width());
|
optionNameRect.width());
|
||||||
painter->drawText(optionNameRect, name);
|
painter->drawText(optionNameRect, name);
|
||||||
|
|
||||||
QPainterPath roundedOptionRect;
|
QPainterPath roundedOptionRect;
|
||||||
@ -157,9 +157,9 @@ void ColorOptionDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
|
|||||||
painter->fillPath(roundedColorRect, currCO.color);
|
painter->fillPath(roundedColorRect, currCO.color);
|
||||||
|
|
||||||
QFontMetrics fm3 = QFontMetrics(painter->font());
|
QFontMetrics fm3 = QFontMetrics(painter->font());
|
||||||
QString desc = fm3.elidedText(
|
QString desc =
|
||||||
currCO.optionName + ": " + optionInfoMap__[currCO.optionName].info, Qt::ElideRight,
|
fm3.elidedText(currCO.optionName + ": " + optionInfoMap__[currCO.optionName].info,
|
||||||
descTextRect.width());
|
Qt::ElideRight, descTextRect.width());
|
||||||
painter->setPen(qApp->palette().text().color());
|
painter->setPen(qApp->palette().text().color());
|
||||||
painter->setBrush(qApp->palette().text());
|
painter->setBrush(qApp->palette().text());
|
||||||
painter->drawText(descTextRect, desc);
|
painter->drawText(descTextRect, desc);
|
||||||
|
@ -12,8 +12,7 @@ ComboQuickFilterView::ComboQuickFilterView(QWidget *parent)
|
|||||||
connect(debounceTimer, &QTimer::timeout, this,
|
connect(debounceTimer, &QTimer::timeout, this,
|
||||||
[this]() { emit filterTextChanged(ui->lineEdit->text()); });
|
[this]() { emit filterTextChanged(ui->lineEdit->text()); });
|
||||||
|
|
||||||
connect(ui->lineEdit, &QLineEdit::textChanged, this,
|
connect(ui->lineEdit, &QLineEdit::textChanged, this, [this]() { debounceTimer->start(150); });
|
||||||
[this](const QString &text) { debounceTimer->start(150); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ComboQuickFilterView::~ComboQuickFilterView()
|
ComboQuickFilterView::~ComboQuickFilterView()
|
||||||
|
@ -173,7 +173,7 @@ void Dashboard::on_certificateButton_clicked()
|
|||||||
dialog.setMinimumSize(QSize(900, 600));
|
dialog.setMinimumSize(QSize(900, 600));
|
||||||
dialog.setMaximumSize(QSize(900, 600));
|
dialog.setMaximumSize(QSize(900, 600));
|
||||||
dialog.setSizeGripEnabled(false);
|
dialog.setSizeGripEnabled(false);
|
||||||
dialog.setWindowTitle("Certificates");
|
dialog.setWindowTitle(tr("Certificates"));
|
||||||
dialog.exec();
|
dialog.exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,8 +26,7 @@ DecompilerWidget::DecompilerWidget(MainWindow *main)
|
|||||||
ui(new Ui::DecompilerWidget),
|
ui(new Ui::DecompilerWidget),
|
||||||
decompilerBusy(false),
|
decompilerBusy(false),
|
||||||
seekFromCursor(false),
|
seekFromCursor(false),
|
||||||
scrollerHorizontal(0),
|
historyPos(0),
|
||||||
scrollerVertical(0),
|
|
||||||
previousFunctionAddr(RVA_INVALID),
|
previousFunctionAddr(RVA_INVALID),
|
||||||
decompiledFunctionAddr(RVA_INVALID),
|
decompiledFunctionAddr(RVA_INVALID),
|
||||||
code(Decompiler::makeWarning(tr("Choose an offset and refresh to get decompiled code")),
|
code(Decompiler::makeWarning(tr("Choose an offset and refresh to get decompiled code")),
|
||||||
@ -91,6 +90,7 @@ DecompilerWidget::DecompilerWidget(MainWindow *main)
|
|||||||
connect(Core(), &CutterCore::varsChanged, this, &DecompilerWidget::doRefresh);
|
connect(Core(), &CutterCore::varsChanged, this, &DecompilerWidget::doRefresh);
|
||||||
connect(Core(), &CutterCore::functionsChanged, this, &DecompilerWidget::doRefresh);
|
connect(Core(), &CutterCore::functionsChanged, this, &DecompilerWidget::doRefresh);
|
||||||
connect(Core(), &CutterCore::flagsChanged, this, &DecompilerWidget::doRefresh);
|
connect(Core(), &CutterCore::flagsChanged, this, &DecompilerWidget::doRefresh);
|
||||||
|
connect(Core(), &CutterCore::globalVarsChanged, this, &DecompilerWidget::doRefresh);
|
||||||
connect(Core(), &CutterCore::commentsChanged, this, &DecompilerWidget::refreshIfChanged);
|
connect(Core(), &CutterCore::commentsChanged, this, &DecompilerWidget::refreshIfChanged);
|
||||||
connect(Core(), &CutterCore::instructionChanged, this, &DecompilerWidget::refreshIfChanged);
|
connect(Core(), &CutterCore::instructionChanged, this, &DecompilerWidget::refreshIfChanged);
|
||||||
connect(Core(), &CutterCore::refreshCodeViews, this, &DecompilerWidget::doRefresh);
|
connect(Core(), &CutterCore::refreshCodeViews, this, &DecompilerWidget::doRefresh);
|
||||||
@ -311,13 +311,6 @@ QTextCursor DecompilerWidget::getCursorForAddress(RVA addr)
|
|||||||
|
|
||||||
void DecompilerWidget::decompilationFinished(RzAnnotatedCode *codeDecompiled)
|
void DecompilerWidget::decompilationFinished(RzAnnotatedCode *codeDecompiled)
|
||||||
{
|
{
|
||||||
bool isDisplayReset = false;
|
|
||||||
if (previousFunctionAddr == decompiledFunctionAddr) {
|
|
||||||
scrollerHorizontal = ui->textEdit->horizontalScrollBar()->sliderPosition();
|
|
||||||
scrollerVertical = ui->textEdit->verticalScrollBar()->sliderPosition();
|
|
||||||
isDisplayReset = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->progressLabel->setVisible(false);
|
ui->progressLabel->setVisible(false);
|
||||||
ui->decompilerComboBox->setEnabled(decompilerSelectionEnabled);
|
ui->decompilerComboBox->setEnabled(decompilerSelectionEnabled);
|
||||||
|
|
||||||
@ -354,10 +347,8 @@ void DecompilerWidget::decompilationFinished(RzAnnotatedCode *codeDecompiled)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDisplayReset) {
|
ui->textEdit->horizontalScrollBar()->setSliderPosition(scrollHistory[historyPos].first);
|
||||||
ui->textEdit->horizontalScrollBar()->setSliderPosition(scrollerHorizontal);
|
ui->textEdit->verticalScrollBar()->setSliderPosition(scrollHistory[historyPos].second);
|
||||||
ui->textEdit->verticalScrollBar()->setSliderPosition(scrollerVertical);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompilerWidget::setAnnotationsAtCursor(size_t pos)
|
void DecompilerWidget::setAnnotationsAtCursor(size_t pos)
|
||||||
@ -416,11 +407,28 @@ void DecompilerWidget::cursorPositionChanged()
|
|||||||
updateSelection();
|
updateSelection();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecompilerWidget::seekChanged()
|
void DecompilerWidget::seekChanged(RVA /* addr */, CutterCore::SeekHistoryType type)
|
||||||
{
|
{
|
||||||
if (seekFromCursor) {
|
if (seekFromCursor) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!scrollHistory.empty()) { // History is empty upon init.
|
||||||
|
scrollHistory[historyPos] = { ui->textEdit->horizontalScrollBar()->sliderPosition(),
|
||||||
|
ui->textEdit->verticalScrollBar()->sliderPosition() };
|
||||||
|
}
|
||||||
|
if (type == CutterCore::SeekHistoryType::New) {
|
||||||
|
// Erase previous history past this point.
|
||||||
|
if (scrollHistory.size() > historyPos + 1) {
|
||||||
|
scrollHistory.erase(scrollHistory.begin() + historyPos + 1, scrollHistory.end());
|
||||||
|
}
|
||||||
|
scrollHistory.push_back({ 0, 0 });
|
||||||
|
historyPos = scrollHistory.size() - 1;
|
||||||
|
} else if (type == CutterCore::SeekHistoryType::Undo) {
|
||||||
|
--historyPos;
|
||||||
|
} else if (type == CutterCore::SeekHistoryType::Redo) {
|
||||||
|
++historyPos;
|
||||||
|
}
|
||||||
RVA fcnAddr = Core()->getFunctionStart(seekable->getOffset());
|
RVA fcnAddr = Core()->getFunctionStart(seekable->getOffset());
|
||||||
if (fcnAddr == RVA_INVALID || fcnAddr != decompiledFunctionAddr) {
|
if (fcnAddr == RVA_INVALID || fcnAddr != decompiledFunctionAddr) {
|
||||||
doRefresh();
|
doRefresh();
|
||||||
|
@ -53,7 +53,7 @@ private slots:
|
|||||||
* - Seek changed to an offset contained in the decompiled function.
|
* - Seek changed to an offset contained in the decompiled function.
|
||||||
* - Auto-refresh is disabled.
|
* - Auto-refresh is disabled.
|
||||||
*/
|
*/
|
||||||
void seekChanged();
|
void seekChanged(RVA /* addr */, CutterCore::SeekHistoryType type);
|
||||||
void decompilationFinished(RzAnnotatedCode *code);
|
void decompilationFinished(RzAnnotatedCode *code);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -72,8 +72,8 @@ private:
|
|||||||
bool decompilerBusy;
|
bool decompilerBusy;
|
||||||
|
|
||||||
bool seekFromCursor;
|
bool seekFromCursor;
|
||||||
int scrollerHorizontal;
|
int historyPos;
|
||||||
int scrollerVertical;
|
QVector<QPair<int, int>> scrollHistory;
|
||||||
RVA previousFunctionAddr;
|
RVA previousFunctionAddr;
|
||||||
RVA decompiledFunctionAddr;
|
RVA decompiledFunctionAddr;
|
||||||
std::unique_ptr<RzAnnotatedCode, void (*)(RzAnnotatedCode *)> code;
|
std::unique_ptr<RzAnnotatedCode, void (*)(RzAnnotatedCode *)> code;
|
||||||
|
@ -52,6 +52,7 @@ DisassemblerGraphView::DisassemblerGraphView(QWidget *parent, CutterSeekable *se
|
|||||||
connect(Core(), &CutterCore::commentsChanged, this, &DisassemblerGraphView::refreshView);
|
connect(Core(), &CutterCore::commentsChanged, this, &DisassemblerGraphView::refreshView);
|
||||||
connect(Core(), &CutterCore::functionRenamed, this, &DisassemblerGraphView::refreshView);
|
connect(Core(), &CutterCore::functionRenamed, this, &DisassemblerGraphView::refreshView);
|
||||||
connect(Core(), &CutterCore::flagsChanged, this, &DisassemblerGraphView::refreshView);
|
connect(Core(), &CutterCore::flagsChanged, this, &DisassemblerGraphView::refreshView);
|
||||||
|
connect(Core(), &CutterCore::globalVarsChanged, this, &DisassemblerGraphView::refreshView);
|
||||||
connect(Core(), &CutterCore::varsChanged, this, &DisassemblerGraphView::refreshView);
|
connect(Core(), &CutterCore::varsChanged, this, &DisassemblerGraphView::refreshView);
|
||||||
connect(Core(), &CutterCore::instructionChanged, this, &DisassemblerGraphView::refreshView);
|
connect(Core(), &CutterCore::instructionChanged, this, &DisassemblerGraphView::refreshView);
|
||||||
connect(Core(), &CutterCore::breakpointsChanged, this, &DisassemblerGraphView::refreshView);
|
connect(Core(), &CutterCore::breakpointsChanged, this, &DisassemblerGraphView::refreshView);
|
||||||
@ -534,17 +535,16 @@ GraphView::EdgeConfiguration DisassemblerGraphView::edgeConfiguration(GraphView:
|
|||||||
|
|
||||||
bool DisassemblerGraphView::eventFilter(QObject *obj, QEvent *event)
|
bool DisassemblerGraphView::eventFilter(QObject *obj, QEvent *event)
|
||||||
{
|
{
|
||||||
if (event->type() == QEvent::Type::ToolTip && Config()->getGraphPreview()) {
|
if ((Config()->getGraphPreview() || Config()->getShowVarTooltips())
|
||||||
|
&& event->type() == QEvent::Type::ToolTip) {
|
||||||
|
|
||||||
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
|
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
|
||||||
QPoint pointOfEvent = helpEvent->globalPos();
|
QPoint pointOfEvent = helpEvent->globalPos();
|
||||||
QPoint point = viewToLogicalCoordinates(helpEvent->pos());
|
QPoint point = viewToLogicalCoordinates(helpEvent->pos());
|
||||||
|
|
||||||
GraphBlock *block = getBlockContaining(point);
|
if (auto block = getBlockContaining(point)) {
|
||||||
|
// Get pos relative to start of block
|
||||||
if (block == nullptr) {
|
QPoint pos = point - QPoint(block->x, block->y);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// offsetFrom is the address which on top the cursor triggered this
|
// offsetFrom is the address which on top the cursor triggered this
|
||||||
RVA offsetFrom = RVA_INVALID;
|
RVA offsetFrom = RVA_INVALID;
|
||||||
@ -553,14 +553,26 @@ bool DisassemblerGraphView::eventFilter(QObject *obj, QEvent *event)
|
|||||||
* getAddrForMouseEvent() doesn't work for jmps, like
|
* getAddrForMouseEvent() doesn't work for jmps, like
|
||||||
* getInstrForMouseEvent() with false as a 3rd argument.
|
* getInstrForMouseEvent() with false as a 3rd argument.
|
||||||
*/
|
*/
|
||||||
Instr *inst = getInstrForMouseEvent(*block, &point, true);
|
Instr *inst = getInstrForMouseEvent(*block, &pos, true);
|
||||||
if (inst != nullptr) {
|
if (inst != nullptr) {
|
||||||
offsetFrom = inst->addr;
|
offsetFrom = inst->addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't preview anything for a small scale
|
// Don't preview anything for a small scale
|
||||||
if (getViewScale() >= 0.8) {
|
if (getViewScale() >= 0.8) {
|
||||||
return DisassemblyPreview::showDisasPreview(this, pointOfEvent, offsetFrom);
|
if (Config()->getGraphPreview()
|
||||||
|
&& DisassemblyPreview::showDisasPreview(this, pointOfEvent, offsetFrom)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Config()->getShowVarTooltips() && inst) {
|
||||||
|
auto token = getToken(inst, pos.x());
|
||||||
|
if (token
|
||||||
|
&& DisassemblyPreview::showDebugValueTooltip(this, pointOfEvent,
|
||||||
|
token->content, offsetFrom)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return CutterGraphView::eventFilter(obj, event);
|
return CutterGraphView::eventFilter(obj, event);
|
||||||
|
@ -128,6 +128,7 @@ DisassemblyWidget::DisassemblyWidget(MainWindow *main)
|
|||||||
|
|
||||||
connect(Core(), &CutterCore::commentsChanged, this, [this]() { refreshDisasm(); });
|
connect(Core(), &CutterCore::commentsChanged, this, [this]() { refreshDisasm(); });
|
||||||
connect(Core(), SIGNAL(flagsChanged()), this, SLOT(refreshDisasm()));
|
connect(Core(), SIGNAL(flagsChanged()), this, SLOT(refreshDisasm()));
|
||||||
|
connect(Core(), SIGNAL(globalVarsChanged()), this, SLOT(refreshDisasm()));
|
||||||
connect(Core(), SIGNAL(functionsChanged()), this, SLOT(refreshDisasm()));
|
connect(Core(), SIGNAL(functionsChanged()), this, SLOT(refreshDisasm()));
|
||||||
connect(Core(), &CutterCore::functionRenamed, this, [this]() { refreshDisasm(); });
|
connect(Core(), &CutterCore::functionRenamed, this, [this]() { refreshDisasm(); });
|
||||||
connect(Core(), SIGNAL(varsChanged()), this, SLOT(refreshDisasm()));
|
connect(Core(), SIGNAL(varsChanged()), this, SLOT(refreshDisasm()));
|
||||||
@ -333,6 +334,7 @@ void DisassemblyWidget::scrollInstructions(int count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
refreshDisasm(offset);
|
refreshDisasm(offset);
|
||||||
|
topOffsetHistory[topOffsetHistoryPos] = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DisassemblyWidget::updateMaxLines()
|
bool DisassemblyWidget::updateMaxLines()
|
||||||
@ -629,21 +631,29 @@ bool DisassemblyWidget::eventFilter(QObject *obj, QEvent *event)
|
|||||||
&& (obj == mDisasTextEdit || obj == mDisasTextEdit->viewport())) {
|
&& (obj == mDisasTextEdit || obj == mDisasTextEdit->viewport())) {
|
||||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||||
|
|
||||||
|
if (mouseEvent->button() == Qt::LeftButton) {
|
||||||
const QTextCursor &cursor = mDisasTextEdit->cursorForPosition(mouseEvent->pos());
|
const QTextCursor &cursor = mDisasTextEdit->cursorForPosition(mouseEvent->pos());
|
||||||
jumpToOffsetUnderCursor(cursor);
|
jumpToOffsetUnderCursor(cursor);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} else if (Config()->getPreviewValue()
|
}
|
||||||
&& event->type() == QEvent::ToolTip
|
} else if ((Config()->getPreviewValue() || Config()->getShowVarTooltips())
|
||||||
&& obj == mDisasTextEdit->viewport()) {
|
&& event->type() == QEvent::ToolTip && obj == mDisasTextEdit->viewport()) {
|
||||||
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
|
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
|
||||||
|
|
||||||
auto cursorForWord = mDisasTextEdit->cursorForPosition(helpEvent->pos());
|
auto cursorForWord = mDisasTextEdit->cursorForPosition(helpEvent->pos());
|
||||||
cursorForWord.select(QTextCursor::WordUnderCursor);
|
cursorForWord.select(QTextCursor::WordUnderCursor);
|
||||||
|
|
||||||
RVA offsetFrom = DisassemblyPreview::readDisassemblyOffset(cursorForWord);
|
RVA offsetFrom = DisassemblyPreview::readDisassemblyOffset(cursorForWord);
|
||||||
|
|
||||||
return DisassemblyPreview::showDisasPreview(this, helpEvent->globalPos(), offsetFrom);
|
if (Config()->getPreviewValue()
|
||||||
|
&& DisassemblyPreview::showDisasPreview(this, helpEvent->globalPos(), offsetFrom)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Config()->getShowVarTooltips()
|
||||||
|
&& DisassemblyPreview::showDebugValueTooltip(
|
||||||
|
this, helpEvent->globalPos(), cursorForWord.selectedText(), offsetFrom)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return MemoryDockWidget::eventFilter(obj, event);
|
return MemoryDockWidget::eventFilter(obj, event);
|
||||||
@ -664,19 +674,34 @@ QString DisassemblyWidget::getWindowTitle() const
|
|||||||
return tr("Disassembly");
|
return tr("Disassembly");
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassemblyWidget::on_seekChanged(RVA offset)
|
void DisassemblyWidget::on_seekChanged(RVA offset, CutterCore::SeekHistoryType type)
|
||||||
{
|
{
|
||||||
|
if (type == CutterCore::SeekHistoryType::New) {
|
||||||
|
// Erase previous history past this point.
|
||||||
|
if (topOffsetHistory.size() > topOffsetHistoryPos + 1) {
|
||||||
|
topOffsetHistory.erase(topOffsetHistory.begin() + topOffsetHistoryPos + 1,
|
||||||
|
topOffsetHistory.end());
|
||||||
|
}
|
||||||
|
topOffsetHistory.push_back(offset);
|
||||||
|
topOffsetHistoryPos = topOffsetHistory.size() - 1;
|
||||||
|
} else if (type == CutterCore::SeekHistoryType::Undo) {
|
||||||
|
--topOffsetHistoryPos;
|
||||||
|
} else if (type == CutterCore::SeekHistoryType::Redo) {
|
||||||
|
++topOffsetHistoryPos;
|
||||||
|
}
|
||||||
if (!seekFromCursor) {
|
if (!seekFromCursor) {
|
||||||
cursorLineOffset = 0;
|
cursorLineOffset = 0;
|
||||||
cursorCharOffset = 0;
|
cursorCharOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (topOffset != RVA_INVALID && offset >= topOffset && offset <= bottomOffset) {
|
if (topOffset != RVA_INVALID && offset >= topOffset && offset <= bottomOffset
|
||||||
|
&& type == CutterCore::SeekHistoryType::New) {
|
||||||
// if the line with the seek offset is currently visible, just move the cursor there
|
// if the line with the seek offset is currently visible, just move the cursor there
|
||||||
updateCursorPosition();
|
updateCursorPosition();
|
||||||
|
topOffsetHistory[topOffsetHistoryPos] = topOffset;
|
||||||
} else {
|
} else {
|
||||||
// otherwise scroll there
|
// otherwise scroll there
|
||||||
refreshDisasm(offset);
|
refreshDisasm(topOffsetHistory[topOffsetHistoryPos]);
|
||||||
}
|
}
|
||||||
mCtxMenu->setOffset(offset);
|
mCtxMenu->setOffset(offset);
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ public slots:
|
|||||||
QList<DisassemblyLine> getLines();
|
QList<DisassemblyLine> getLines();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void on_seekChanged(RVA offset);
|
void on_seekChanged(RVA offset, CutterCore::SeekHistoryType type);
|
||||||
void refreshIfInRange(RVA offset);
|
void refreshIfInRange(RVA offset);
|
||||||
void instructionChanged(RVA offset);
|
void instructionChanged(RVA offset);
|
||||||
void refreshDisasm(RVA offset = RVA_INVALID);
|
void refreshDisasm(RVA offset = RVA_INVALID);
|
||||||
@ -88,6 +88,9 @@ private:
|
|||||||
void keyPressEvent(QKeyEvent *event) override;
|
void keyPressEvent(QKeyEvent *event) override;
|
||||||
QString getWindowTitle() const override;
|
QString getWindowTitle() const override;
|
||||||
|
|
||||||
|
int topOffsetHistoryPos = 0;
|
||||||
|
QList<RVA> topOffsetHistory;
|
||||||
|
|
||||||
QList<RVA> breakpoints;
|
QList<RVA> breakpoints;
|
||||||
|
|
||||||
void setupFonts();
|
void setupFonts();
|
||||||
|
@ -234,9 +234,8 @@ QVariant FunctionModel::data(const QModelIndex &index, int role) const
|
|||||||
QStringList summary {};
|
QStringList summary {};
|
||||||
{
|
{
|
||||||
auto seeker = Core()->seekTemp(function.offset);
|
auto seeker = Core()->seekTemp(function.offset);
|
||||||
auto strings = fromOwnedCharPtr(
|
auto strings = fromOwnedCharPtr(rz_core_print_disasm_strings(
|
||||||
rz_core_print_disasm_strings(Core()->core(), RZ_CORE_DISASM_STRINGS_MODE_FUNCTION,
|
Core()->core(), RZ_CORE_DISASM_STRINGS_MODE_FUNCTION, 0, NULL));
|
||||||
0, NULL));
|
|
||||||
summary = strings.split('\n', CUTTER_QT_SKIP_EMPTY_PARTS);
|
summary = strings.split('\n', CUTTER_QT_SKIP_EMPTY_PARTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,6 +507,7 @@ FunctionsWidget::FunctionsWidget(MainWindow *main)
|
|||||||
functionProxyModel = new FunctionSortFilterProxyModel(functionModel, this);
|
functionProxyModel = new FunctionSortFilterProxyModel(functionModel, this);
|
||||||
setModels(functionProxyModel);
|
setModels(functionProxyModel);
|
||||||
ui->treeView->sortByColumn(FunctionModel::NameColumn, Qt::AscendingOrder);
|
ui->treeView->sortByColumn(FunctionModel::NameColumn, Qt::AscendingOrder);
|
||||||
|
ui->treeView->setExpandsOnDoubleClick(false);
|
||||||
|
|
||||||
titleContextMenu = new QMenu(this);
|
titleContextMenu = new QMenu(this);
|
||||||
auto viewTypeGroup = new QActionGroup(titleContextMenu);
|
auto viewTypeGroup = new QActionGroup(titleContextMenu);
|
||||||
|
228
src/widgets/GlobalsWidget.cpp
Normal file
228
src/widgets/GlobalsWidget.cpp
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
#include "GlobalsWidget.h"
|
||||||
|
#include "ui_GlobalsWidget.h"
|
||||||
|
#include "core/MainWindow.h"
|
||||||
|
#include "common/Helpers.h"
|
||||||
|
#include "dialogs/GlobalVariableDialog.h"
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QShortcut>
|
||||||
|
|
||||||
|
GlobalsModel::GlobalsModel(QList<GlobalDescription> *globals, QObject *parent)
|
||||||
|
: AddressableItemModel<QAbstractListModel>(parent), globals(globals)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int GlobalsModel::rowCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return globals->count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GlobalsModel::columnCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
return GlobalsModel::ColumnCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant GlobalsModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (index.row() >= globals->count()) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
const GlobalDescription &global = globals->at(index.row());
|
||||||
|
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (index.column()) {
|
||||||
|
case GlobalsModel::AddressColumn:
|
||||||
|
return RzAddressString(global.addr);
|
||||||
|
case GlobalsModel::TypeColumn:
|
||||||
|
return QString(global.type).trimmed();
|
||||||
|
case GlobalsModel::NameColumn:
|
||||||
|
return global.name;
|
||||||
|
case GlobalsModel::CommentColumn:
|
||||||
|
return Core()->getCommentAt(global.addr);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
case GlobalsModel::GlobalDescriptionRole:
|
||||||
|
return QVariant::fromValue(global);
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant GlobalsModel::headerData(int section, Qt::Orientation, int role) const
|
||||||
|
{
|
||||||
|
switch (role) {
|
||||||
|
case Qt::DisplayRole:
|
||||||
|
switch (section) {
|
||||||
|
case GlobalsModel::AddressColumn:
|
||||||
|
return tr("Address");
|
||||||
|
case GlobalsModel::TypeColumn:
|
||||||
|
return tr("Type");
|
||||||
|
case GlobalsModel::NameColumn:
|
||||||
|
return tr("Name");
|
||||||
|
case GlobalsModel::CommentColumn:
|
||||||
|
return tr("Comment");
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RVA GlobalsModel::address(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
const GlobalDescription &global = globals->at(index.row());
|
||||||
|
return global.addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GlobalsModel::name(const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
const GlobalDescription &global = globals->at(index.row());
|
||||||
|
return global.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalsProxyModel::GlobalsProxyModel(GlobalsModel *sourceModel, QObject *parent)
|
||||||
|
: AddressableFilterProxyModel(sourceModel, parent)
|
||||||
|
{
|
||||||
|
setFilterCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
setSortCaseSensitivity(Qt::CaseInsensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GlobalsProxyModel::filterAcceptsRow(int row, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
QModelIndex index = sourceModel()->index(row, 0, parent);
|
||||||
|
auto global = index.data(GlobalsModel::GlobalDescriptionRole).value<GlobalDescription>();
|
||||||
|
|
||||||
|
return qhelpers::filterStringContains(global.name, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GlobalsProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||||
|
{
|
||||||
|
auto leftGlobal = left.data(GlobalsModel::GlobalDescriptionRole).value<GlobalDescription>();
|
||||||
|
auto rightGlobal = right.data(GlobalsModel::GlobalDescriptionRole).value<GlobalDescription>();
|
||||||
|
|
||||||
|
switch (left.column()) {
|
||||||
|
case GlobalsModel::AddressColumn:
|
||||||
|
return leftGlobal.addr < rightGlobal.addr;
|
||||||
|
case GlobalsModel::TypeColumn:
|
||||||
|
return leftGlobal.type < rightGlobal.type;
|
||||||
|
case GlobalsModel::NameColumn:
|
||||||
|
return leftGlobal.name < rightGlobal.name;
|
||||||
|
case GlobalsModel::CommentColumn:
|
||||||
|
return Core()->getCommentAt(leftGlobal.addr) < Core()->getCommentAt(rightGlobal.addr);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalsWidget::editGlobal()
|
||||||
|
{
|
||||||
|
QModelIndex index = ui->treeView->currentIndex();
|
||||||
|
|
||||||
|
if (!index.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RVA globalVariableAddress = globalsModel->address(index);
|
||||||
|
|
||||||
|
GlobalVariableDialog dialog(globalVariableAddress, parentWidget());
|
||||||
|
dialog.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalsWidget::deleteGlobal()
|
||||||
|
{
|
||||||
|
QModelIndex index = ui->treeView->currentIndex();
|
||||||
|
|
||||||
|
if (!index.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RVA globalVariableAddress = globalsModel->address(index);
|
||||||
|
Core()->delGlobalVariable(globalVariableAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GlobalsWidget::showGlobalsContextMenu(const QPoint &pt)
|
||||||
|
{
|
||||||
|
QModelIndex index = ui->treeView->indexAt(pt);
|
||||||
|
|
||||||
|
QMenu menu(ui->treeView);
|
||||||
|
|
||||||
|
if (index.isValid()) {
|
||||||
|
menu.addAction(actionEditGlobal);
|
||||||
|
menu.addAction(actionDeleteGlobal);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.exec(ui->treeView->mapToGlobal(pt));
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalsWidget::GlobalsWidget(MainWindow *main)
|
||||||
|
: CutterDockWidget(main), ui(new Ui::GlobalsWidget), tree(new CutterTreeWidget(this))
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
ui->quickFilterView->setLabelText(tr("Category"));
|
||||||
|
|
||||||
|
setWindowTitle(tr("Globals"));
|
||||||
|
setObjectName("GlobalsWidget");
|
||||||
|
|
||||||
|
// Add status bar which displays the count
|
||||||
|
tree->addStatusBar(ui->verticalLayout);
|
||||||
|
|
||||||
|
// Set single select mode
|
||||||
|
ui->treeView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
|
|
||||||
|
// Setup up the model and the proxy model
|
||||||
|
globalsModel = new GlobalsModel(&globals, this);
|
||||||
|
globalsProxyModel = new GlobalsProxyModel(globalsModel, this);
|
||||||
|
ui->treeView->setModel(globalsProxyModel);
|
||||||
|
ui->treeView->sortByColumn(GlobalsModel::AddressColumn, Qt::AscendingOrder);
|
||||||
|
|
||||||
|
// Setup custom context menu
|
||||||
|
connect(ui->treeView, &QWidget::customContextMenuRequested, this,
|
||||||
|
&GlobalsWidget::showGlobalsContextMenu);
|
||||||
|
|
||||||
|
ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
|
|
||||||
|
connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, globalsProxyModel,
|
||||||
|
&QSortFilterProxyModel::setFilterWildcard);
|
||||||
|
|
||||||
|
connect(ui->quickFilterView, &ComboQuickFilterView::filterTextChanged, this,
|
||||||
|
[this] { tree->showItemsNumber(globalsProxyModel->rowCount()); });
|
||||||
|
|
||||||
|
QShortcut *searchShortcut = new QShortcut(QKeySequence::Find, this);
|
||||||
|
connect(searchShortcut, &QShortcut::activated, ui->quickFilterView,
|
||||||
|
&ComboQuickFilterView::showFilter);
|
||||||
|
searchShortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
||||||
|
|
||||||
|
QShortcut *clearShortcut = new QShortcut(QKeySequence(Qt::Key_Escape), this);
|
||||||
|
connect(clearShortcut, &QShortcut::activated, ui->quickFilterView,
|
||||||
|
&ComboQuickFilterView::clearFilter);
|
||||||
|
clearShortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
||||||
|
|
||||||
|
actionEditGlobal = new QAction(tr("Edit Global Variable"), this);
|
||||||
|
actionDeleteGlobal = new QAction(tr("Delete Global Variable"), this);
|
||||||
|
|
||||||
|
connect(actionEditGlobal, &QAction::triggered, [this]() { editGlobal(); });
|
||||||
|
connect(actionDeleteGlobal, &QAction::triggered, [this]() { deleteGlobal(); });
|
||||||
|
|
||||||
|
connect(Core(), &CutterCore::globalVarsChanged, this, &GlobalsWidget::refreshGlobals);
|
||||||
|
connect(Core(), &CutterCore::codeRebased, this, &GlobalsWidget::refreshGlobals);
|
||||||
|
connect(Core(), &CutterCore::refreshAll, this, &GlobalsWidget::refreshGlobals);
|
||||||
|
connect(Core(), &CutterCore::commentsChanged, this,
|
||||||
|
[this]() { qhelpers::emitColumnChanged(globalsModel, GlobalsModel::CommentColumn); });
|
||||||
|
}
|
||||||
|
|
||||||
|
GlobalsWidget::~GlobalsWidget() {}
|
||||||
|
|
||||||
|
void GlobalsWidget::refreshGlobals()
|
||||||
|
{
|
||||||
|
globalsModel->beginResetModel();
|
||||||
|
globals = Core()->getAllGlobals();
|
||||||
|
globalsModel->endResetModel();
|
||||||
|
|
||||||
|
qhelpers::adjustColumns(ui->treeView, GlobalsModel::ColumnCount, 0);
|
||||||
|
}
|
89
src/widgets/GlobalsWidget.h
Normal file
89
src/widgets/GlobalsWidget.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#ifndef GLOBALSWIDGET_H
|
||||||
|
#define GLOBALSWIDGET_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
|
#include "core/Cutter.h"
|
||||||
|
#include "CutterDockWidget.h"
|
||||||
|
#include "widgets/ListDockWidget.h"
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
class QTreeWidget;
|
||||||
|
class GlobalsWidget;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class GlobalsWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MainWindow;
|
||||||
|
class QTreeWidgetItem;
|
||||||
|
|
||||||
|
class GlobalsModel : public AddressableItemModel<QAbstractListModel>
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
friend GlobalsWidget;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<GlobalDescription> *globals;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum Column { AddressColumn = 0, TypeColumn, NameColumn, CommentColumn, ColumnCount };
|
||||||
|
enum Role { GlobalDescriptionRole = Qt::UserRole };
|
||||||
|
|
||||||
|
GlobalsModel(QList<GlobalDescription> *exports, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation,
|
||||||
|
int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
RVA address(const QModelIndex &index) const override;
|
||||||
|
QString name(const QModelIndex &index) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GlobalsProxyModel : public AddressableFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
GlobalsProxyModel(GlobalsModel *sourceModel, QObject *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool filterAcceptsRow(int row, const QModelIndex &parent) const override;
|
||||||
|
bool lessThan(const QModelIndex &left, const QModelIndex &right) const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GlobalsWidget : public CutterDockWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GlobalsWidget(MainWindow *main);
|
||||||
|
~GlobalsWidget();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void refreshGlobals();
|
||||||
|
|
||||||
|
void showGlobalsContextMenu(const QPoint &pt);
|
||||||
|
|
||||||
|
void editGlobal();
|
||||||
|
void deleteGlobal();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Ui::GlobalsWidget> ui;
|
||||||
|
|
||||||
|
QList<GlobalDescription> globals;
|
||||||
|
GlobalsModel *globalsModel;
|
||||||
|
GlobalsProxyModel *globalsProxyModel;
|
||||||
|
CutterTreeWidget *tree;
|
||||||
|
|
||||||
|
QAction *actionEditGlobal;
|
||||||
|
QAction *actionDeleteGlobal;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GLOBALSWIDGET_H
|
107
src/widgets/GlobalsWidget.ui
Normal file
107
src/widgets/GlobalsWidget.ui
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>GlobalsWidget</class>
|
||||||
|
<widget class="QDockWidget" name="GlobalsWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string notr="true">Global Variables</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="dockWidgetContents">
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="CutterTreeView" name="treeView">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">CutterTreeView::item
|
||||||
|
{
|
||||||
|
padding-top: 1px;
|
||||||
|
padding-bottom: 1px;
|
||||||
|
}</string>
|
||||||
|
</property>
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::NoFrame</enum>
|
||||||
|
</property>
|
||||||
|
<property name="lineWidth">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="indentation">
|
||||||
|
<number>8</number>
|
||||||
|
</property>
|
||||||
|
<property name="sortingEnabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="ComboQuickFilterView" name="quickFilterView" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<action name="actionEditGlobal">
|
||||||
|
<property name="text">
|
||||||
|
<string>Edit Global Variable</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Edit Global Variable</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
<action name="actionDeleteGlobal">
|
||||||
|
<property name="text">
|
||||||
|
<string>Delete Global Variable</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Delete Global Variable</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>CutterTreeView</class>
|
||||||
|
<extends>QTreeView</extends>
|
||||||
|
<header>widgets/CutterTreeView.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>ComboQuickFilterView</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>widgets/ComboQuickFilterView.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -438,7 +438,7 @@ void GraphView::saveAsSvg(QString path)
|
|||||||
generator.setFileName(path);
|
generator.setFileName(path);
|
||||||
generator.setSize(QSize(width, height));
|
generator.setSize(QSize(width, height));
|
||||||
generator.setViewBox(QRect(0, 0, width, height));
|
generator.setViewBox(QRect(0, 0, width, height));
|
||||||
generator.setTitle("Cutter graph export");
|
generator.setTitle(tr("Cutter graph export"));
|
||||||
QPainter p;
|
QPainter p;
|
||||||
p.begin(&generator);
|
p.begin(&generator);
|
||||||
paint(p, QPoint(0, 0), QRect(0, 0, width, height), 1.0, false);
|
paint(p, QPoint(0, 0), QRect(0, 0, width, height), 1.0, false);
|
||||||
|
@ -36,8 +36,7 @@ void HeapBinsGraphView::loadCurrentGraph()
|
|||||||
|| QString(heapBin->type) == QString("Tcache");
|
|| QString(heapBin->type) == QString("Tcache");
|
||||||
|
|
||||||
// store info about the chunks in a vector for easy access
|
// store info about the chunks in a vector for easy access
|
||||||
CutterRzListForeach(heapBin->chunks, iter, RzHeapChunkListItem, item)
|
CutterRzListForeach (heapBin->chunks, iter, RzHeapChunkListItem, item) {
|
||||||
{
|
|
||||||
GraphHeapChunk graphHeapChunk;
|
GraphHeapChunk graphHeapChunk;
|
||||||
graphHeapChunk.addr = item->addr;
|
graphHeapChunk.addr = item->addr;
|
||||||
RzHeapChunkSimple *chunkInfo = Core()->getHeapChunk(item->addr);
|
RzHeapChunkSimple *chunkInfo = Core()->getHeapChunk(item->addr);
|
||||||
|
@ -1407,8 +1407,8 @@ void HexWidget::w_writeRandom()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
int nbytes = QInputDialog::getInt(this, tr("Write random bytes"), tr("Number of bytes:"), size, 1,
|
int nbytes = QInputDialog::getInt(this, tr("Write random bytes"), tr("Number of bytes:"), size,
|
||||||
0x7FFFFFFF, 1, &ok);
|
1, 0x7FFFFFFF, 1, &ok);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -248,19 +248,24 @@ void HexdumpWidget::updateParseWindow(RVA start_address, int size)
|
|||||||
ut64 old_offset = core->offset;
|
ut64 old_offset = core->offset;
|
||||||
rz_core_seek(core, start_address, true);
|
rz_core_seek(core, start_address, true);
|
||||||
ut8 *block = core->block;
|
ut8 *block = core->block;
|
||||||
char *digest = rz_hash_cfg_calculate_small_block_string(core->hash, "md5", block, size, &digest_size, false);
|
char *digest = rz_hash_cfg_calculate_small_block_string(core->hash, "md5", block, size,
|
||||||
|
&digest_size, false);
|
||||||
ui->bytesMD5->setText(QString(digest));
|
ui->bytesMD5->setText(QString(digest));
|
||||||
free(digest);
|
free(digest);
|
||||||
digest = rz_hash_cfg_calculate_small_block_string(core->hash, "sha1", block, size, &digest_size, false);
|
digest = rz_hash_cfg_calculate_small_block_string(core->hash, "sha1", block, size,
|
||||||
|
&digest_size, false);
|
||||||
ui->bytesSHA1->setText(QString(digest));
|
ui->bytesSHA1->setText(QString(digest));
|
||||||
free(digest);
|
free(digest);
|
||||||
digest = rz_hash_cfg_calculate_small_block_string(core->hash, "sha256", block, size, &digest_size, false);
|
digest = rz_hash_cfg_calculate_small_block_string(core->hash, "sha256", block, size,
|
||||||
|
&digest_size, false);
|
||||||
ui->bytesSHA256->setText(QString(digest));
|
ui->bytesSHA256->setText(QString(digest));
|
||||||
free(digest);
|
free(digest);
|
||||||
digest = rz_hash_cfg_calculate_small_block_string(core->hash, "crc32", block, size, &digest_size, false);
|
digest = rz_hash_cfg_calculate_small_block_string(core->hash, "crc32", block, size,
|
||||||
|
&digest_size, false);
|
||||||
ui->bytesCRC32->setText(QString(digest));
|
ui->bytesCRC32->setText(QString(digest));
|
||||||
free(digest);
|
free(digest);
|
||||||
digest = rz_hash_cfg_calculate_small_block_string(core->hash, "entropy", block, size, &digest_size, false);
|
digest = rz_hash_cfg_calculate_small_block_string(core->hash, "entropy", block, size,
|
||||||
|
&digest_size, false);
|
||||||
ui->bytesEntropy->setText(QString(digest));
|
ui->bytesEntropy->setText(QString(digest));
|
||||||
free(digest);
|
free(digest);
|
||||||
rz_core_seek(core, old_offset, true);
|
rz_core_seek(core, old_offset, true);
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include "ui_ListDockWidget.h"
|
#include "ui_ListDockWidget.h"
|
||||||
#include "core/MainWindow.h"
|
#include "core/MainWindow.h"
|
||||||
#include "common/Helpers.h"
|
#include "common/Helpers.h"
|
||||||
#include "menus/AddressableItemContextMenu.h"
|
|
||||||
|
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QResizeEvent>
|
#include <QResizeEvent>
|
||||||
|
@ -16,7 +16,7 @@ QuickFilterView::QuickFilterView(QWidget *parent, bool defaultOn)
|
|||||||
[this]() { emit filterTextChanged(ui->filterLineEdit->text()); });
|
[this]() { emit filterTextChanged(ui->filterLineEdit->text()); });
|
||||||
|
|
||||||
connect(ui->filterLineEdit, &QLineEdit::textChanged, this,
|
connect(ui->filterLineEdit, &QLineEdit::textChanged, this,
|
||||||
[this](const QString &text) { debounceTimer->start(150); });
|
[this]() { debounceTimer->start(150); });
|
||||||
|
|
||||||
if (!defaultOn) {
|
if (!defaultOn) {
|
||||||
closeFilter();
|
closeFilter();
|
||||||
|
@ -27,6 +27,7 @@ RizinGraphWidget::RizinGraphWidget(MainWindow *main)
|
|||||||
{ 'r', tr("References graph (agr)") },
|
{ 'r', tr("References graph (agr)") },
|
||||||
{ 'R', tr("Global references graph (agR)") },
|
{ 'R', tr("Global references graph (agR)") },
|
||||||
{ 'x', tr("Cross references graph (agx)") },
|
{ 'x', tr("Cross references graph (agx)") },
|
||||||
|
{ 'I', tr("RzIL statement graph (agI)") },
|
||||||
{ 'g', tr("Custom graph (agg)") },
|
{ 'g', tr("Custom graph (agg)") },
|
||||||
{ ' ', tr("User command") },
|
{ ' ', tr("User command") },
|
||||||
};
|
};
|
||||||
|
@ -322,12 +322,12 @@ void SearchWidget::updatePlaceholderText(int index)
|
|||||||
void SearchWidget::disableSearch()
|
void SearchWidget::disableSearch()
|
||||||
{
|
{
|
||||||
ui->searchButton->setEnabled(false);
|
ui->searchButton->setEnabled(false);
|
||||||
ui->searchButton->setText("Searching...");
|
ui->searchButton->setText(tr("Searching..."));
|
||||||
qApp->processEvents();
|
qApp->processEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchWidget::enableSearch()
|
void SearchWidget::enableSearch()
|
||||||
{
|
{
|
||||||
ui->searchButton->setEnabled(true);
|
ui->searchButton->setEnabled(true);
|
||||||
ui->searchButton->setText("Search");
|
ui->searchButton->setText(tr("Search"));
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user