- 应用安全
- 桌面应用
- 开发工具
【免费下载链接】cutter
Free and Open Source Reverse Engineering Platform powered by rizin
本文基于 Cutter 官方开发者文档整理而成。Cutter 是一款由 rizin 驱动的免费开源逆向工程平台,本文面向希望为其贡献代码的开发者:从编译源码、挑选 Issue,到遵循 CutterCore 开发模式与编码规范、提交 Pull Request,再到在 Qt Creator、VS Code、CLion、Visual Studio 等主流 IDE 中搭建开发环境,逐步给出可落地的操作路径。读完本文,你将掌握一套完整的 Cutter 代码贡献工作流。
开发者文档导航:三份核心文档
Cutter 的开发者文档入口位于 docs/source/contributing/code.rst,它本身是一个 toctree 索引页,将开发者内容组织为三个子文档,作为新贡献者应首先通读:
- 新开发者教程:code/getting-started.rst —— 完整的贡献流程:克隆编译、挑选 Issue、定位源码、编写代码、提交 PR;
- 开发指南:code/development-guidelines.rst —— 编码规范与代码约定:CutterCore 使用方式、命名规则、Qt 信号连接、clang-format/clang-tidy 工具链等;
- 开发环境配置:code/ide-setup.rst —— 在 Qt Creator、VS Code、CLion、Visual Studio 中搭建开发环境的具体建议。
此外,docs/source/building.rst 详细描述了各平台的命令行编译步骤(含 Troubleshooting),docs/source/contributing.rst 则汇总了代码、文档、插件、翻译四条贡献路线。若你遇到构建问题,优先查阅 building 文档中的Building:Troubleshooting一节;若需要 IDE 配置建议,则阅读 ide-setup 文档。
第一步:克隆并编译 Cutter
在开始写代码之前,必须先在自己的环境(Linux、Windows 或 macOS)上成功构建 Cutter,并验证它能正常运行。
克隆源码时需携带子模块(Rizin 是 Cutter 的核心依赖,以 submodule 形式存在于rizin/目录):
git clone --recurse-submodules https://github.com/rizinorg/cutter克隆完成后会得到如下目录结构:
cutter/- |-docs/ # Cutter 文档 |-rizin/ # Rizin 子模块 |-src/ # Cutter 源码在 Linux 上,推荐使用 CMake 构建(默认会自动编译 bundled Rizin):
mkdir build && cd build cmake .. cmake --build .CMake 3.12+ 可简化为:
cmake -B build cmake --build build构建完成后,可执行文件Cutter位于build/目录下,运行:
./build/cutter常用的 Cutter CMake 构建选项
仓库根目录的 CMakeLists.txt 中定义了完整的构建选项,以下为开发中最常涉及的几个:
| 选项 | 默认值 | 说明 |
|---|---|---|
CUTTER_USE_BUNDLED_RIZIN | ON | 从./rizin子模块自动编译 Rizin,而非搜索系统安装的 Rizin(定义于 CMakeLists.txt) |
CUTTER_ENABLE_PYTHON | OFF | 启用 Python 集成,Python 插件的前置条件 |
CUTTER_ENABLE_PYTHON_BINDINGS | OFF | 使用 Shiboken 自动生成 Python 绑定,Python 插件的必要条件 |
CUTTER_ENABLE_KSYNTAXHIGHLIGHTING | 默认开启 | 使用 KSyntaxHighlighting 进行代码高亮 |
CUTTER_ENABLE_GRAPHVIZ | 默认开启 | 启用 Graphviz 图布局 |
CUTTER_ENABLE_TRANSLATIONS | ON | 构建并安装翻译文件(见 CMakeLists.txt) |
CUTTER_ENABLE_SIGDB | OFF | 下载并安装 sigdb(仅在CUTTER_USE_BUNDLED_RIZIN=ON时可用,见 CMakeLists.txt) |
CUTTER_QT | 6 | Qt 主版本号,允许值为5、6(见 CMakeLists.txt) |
CUTTER_INCLUDE_GIT_HASH | ON | 在完整版本字符串中包含 git 提交哈希 |
CUTTER_VERSION_SUFFIX | 空 | 打包方用于区分基于同一上游版本的多个构建 |
CUTTER_EXTRA_PLUGIN_DIRS | 空 | 额外插件搜索路径列表,适用于 Linux 发行版打包 |
CUTTER_ENABLE_DEPENDENCY_DOWNLOADS | OFF | 启用依赖下载,主要用于 CI 环境准备二进制发布包 |
CUTTER_PACKAGE_DEPENDENCIES | OFF | 安装步骤中包含第三方依赖,用于发布包 |
配置示例:构建带 Python 插件支持的版本:
cmake -B build -DCUTTER_ENABLE_PYTHON=ON -DCUTTER_ENABLE_PYTHON_BINDINGS=ON显式关闭某个选项:
cmake -B build -DCUTTER_ENABLE_PYTHON=OFF开发建议:除非你正在处理打包相关问题,否则推荐使用默认的 bundled Rizin 配置(即保持
CUTTER_USE_BUNDLED_RIZIN=ON)。它是确保 Rizin 版本兼容的最简单方式,也便于在多个 Cutter 分支之间切换。若需使用系统安装的其他版本 Rizin,可设置CUTTER_USE_BUNDLED_RIZIN=OFF;在 Linux 上,若存在多个 Rizin 版本,可通过PKG_CONFIG_PATH环境变量指定所需安装。注意:使用与 Cutter 不匹配的 Rizin 版本可能导致编译失败。
常见故障排查(详见 docs/source/building.rst):
- CMake 找不到 Qt:确认 Qt 版本正确,找到其 prefix(包含 bin/、lib/、include/ 的目录),通过
CMAKE_PREFIX_PATH指定,例如cmake -DCMAKE_PREFIX_PATH=/opt/Qt/5.9.1/gcc_64 ..; - 运行 Cutter 时提示找不到
librz_*.so:部分系统 linker 默认使用 RUNPATH 而非 RPATH,可添加-DCMAKE_EXE_LINKER_FLAGS="-Wl,--disable-new-dtags"重新编译,或将 Rizin 安装路径加入LD_LIBRARY_PATH; rz_*.h: No such file or directory:检查rizin/子模块是否与上游同步,运行git submodule update --init --recursive;rz_core development package not found:PATH环境变量可能不包含/usr/local/bin,将其加入PATH,macOS 上可在 Qt Creator 的Build Environment中追加。
第二步:找到适合自己的任务
如果暂时没有明确想做的功能,可以从 Cutter 的 Issue 与 feature-request 列表出发。Cutter 使用 GitHub 的多个项目管理和追踪功能来组织成百上千个 Issue,熟悉它们有助于快速筛选:
- Labels:Issue 与 PR 的标签用于描述类型、所属功能、难度和优先级。建议从
good-first-issue标签开始,这些 Issue 已被维护者标记为适合新贡献者; - Projects:项目看板按特定功能或问题聚合任务。Cutter 为调试器、Hexdump 组件、反编译组件、High DPI 支持等设有专属看板,适合想参与大型功能或了解某模块进展的贡献者;
- Milestones:每个新版本发布前,维护者会把高优先级的 bug 和 feature 请求汇聚到里程碑中。若想参与下一版本最需要的工作,可以关注开放的 Milestone;
- Issue 认领:挑选 Issue 前先确认其未被他人认领;若已被认领,可以在评论区询问认领者是否有意继续。部分已认领的 Issue 实际已被弃置,可被其他贡献者接手。
提示:修复自己最困扰的 "pet peeve" 是一个绝佳的起点——任何让你对 Cutter 感到不便的具体问题,都可能是一个合适的切入点。
第三步:熟悉现状并定位源码
动手前,先运行 Cutter 熟悉你要修改的功能当前的行为。例如:若是对话框,理解其角色与用户使用方式;若是 bug,按照 bug 报告中的步骤尝试复现。
定位实现该功能的源文件时,推荐两种方法:
- 按功能名搜索文件:例如想改进 "Sections" 组件,可在源码中寻找
SectionsWidget.cpp与SectionsWidget.h(实际位于 src/widgets/SectionsWidget.cpp 与 src/widgets/SectionsWidget.h); - 搜索界面中出现的独特字符串:在整个代码库中搜索对话框、组件或功能中出现的字符串,通常能定位到相关的
.cpp或.ui文件,再由此导航到正确位置。Cutter 的源码集中在src/目录下,组件类位于 src/widgets,对话框位于 src/dialogs,核心逻辑位于 src/core 与 src/common。
若对二进制分析任务不熟悉,可以随时在社区向其他开发者请教该功能的设计意图与使用方法。
第四步:理解 CutterCore——与 Rizin 交互的唯一入口
开发指南(code/development-guidelines.rst)强调,CutterCore 是整个进程中与 Rizin 建立联系的唯一主类,全进程唯一,通过Core()即可访问:
Core()->getOffset();使用seek修改当前寻址位置
修改 Rizin 的 seek 必须使用CutterCore::seek(const RVA offset),因为该方法会发出CutterCore::seekChanged(RVA offset)信号,驱动各组件刷新。永远不要调用cmd("s offset")直接操作 Rizin。
Core()->seek(0x00C0FFEE);从 src/core/Cutter.cpp 的源码实现可以看到,seek(ut64 offset)内部通过rz_core_seek_and_save执行寻址,并在地址变化时调用updateSeek();而seek(const QString &thing)(src/core/Cutter.cpp)则先用rz_num_math解析表达式再寻址。
Cutter 还支持静默寻址(seekSilent),它不会触发seekChanged事件,也不会向 seek 历史中添加新条目——适用于不希望界面随之刷新的场景,其实现见 src/core/Cutter.cpp:
void CutterCore::seekSilent(ut64 offset) { CORE_LOCK(); if (offset == RVA_INVALID) { return; } rz_core_seek(core, offset, true); }创建 Widget 时连接 seekChanged 信号
新增 Widget 时,务必连接CutterCore::seekChanged(RVA offset)信号,使其在 Rizin seek 改变(如切换到另一个函数)时刷新输出。这是 Cutter 组件间同步的核心机制。
第五步:编码规范与工具链
开发指南规定,Cutter 大体遵循 Qt 官方编码风格 的定制版本,并强制使用clang-format与clang-tidy检查。
clang-format
提交 Pull Request 前,需要用 clang-format(8.0 或更新版本)格式化代码。仓库根目录的 _clang-format 定义了项目专用规则(由 scripts/update_clang_format.sh 生成,基于 clang-format 15.0.4),其中关键的定制项包括:列宽上限 100、缩进 4 空格、强制单行条件语句加花括号(InsertBraces: true)、include 分组重排(IncludeBlocks: Regroup)、Qt 头文件归入第二优先级等。
格式化单个文件:
clang-format -style=file -i src/filename.cpp若改动涉及整个src目录的多个文件,可对全部源码执行:
find ./src -regex '.*\.\(cpp\|h\)' -exec clang-format -style=file -i {} \;clang-tidy
在格式化之外,使用 clang-tidy(13.0 或更新版本)捕捉潜在风格违规。首先配置构建以生成compile_commands.json并运行 autogen 工具:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCUTTER_QT=6 -DCUTTER_USE_BUNDLED_RIZIN=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON cmake --build build --target Cutter_autogen对自最近一次提交以来修改过的文件运行 clang-tidy:
git diff -U0 --no-color HEAD~1 | clang-tidy-diff.py -p1 -path build/对整个src目录运行(排除第三方与自动生成文件,正则来自 scripts/clang-tidy.py 中的DEFAULT_REGEX):
run-clang-tidy -p build ".*src/(?!(themes|bindings|fonts|img|translations|Cutter_autogen)).*\.(cpp|h)$"clang-tidy 还支持-fix自动修复风格违规,但修复不一定完美,提交 PR 前务必人工核对:
git diff -U0 --no-color HEAD~1 | clang-tidy-diff.py -fix -p1 -path build/仓库自带的 Python 封装脚本
Cutter 在 scripts 目录下提供了封装脚本,避免手敲上述命令。python scripts/clang-format.py -h输出的参数如下:
usage: clang-format.py [-h] [-C CLANG_FORMAT] [-c] [-v] [-f FILE] [-d DIFF] Clang format the cutter project options: -h, --help show this help message and exit -C, --clang-format CLANG_FORMAT path of clang-format -c, --check enable the check mode -v, --verbose use verbose output -f, --file FILE formats (or checks) only the given file -d, --diff DIFF format all modified file related to branch从源码(scripts/clang-format.py)看,该脚本扫描src目录下的*.cpp、*.h、*.hpp(跳过translations),支持单文件、diff 分支改动或全目录三种模式;-c/--check以--Werror --dry-run方式仅检查而不改写,适合 CI。
clang-tidy.py的用法为:
usage: clang-tidy.py [-h] [-T RUN_CLANG_TIDY] [-p BUILD_PATH] [-j JOBS] [-r REGEX] [-i] [-q] clang-tidy regex wrapper options: -h, --help show this help message and exit -T, --run-clang-tidy RUN_CLANG_TIDY Path of run-clang-tidy binary -p, --build-path BUILD_PATH Path to the build directory -j, --jobs JOBS Number of parallel execution jobs -r, --regex REGEX Regex pattern for filtering files -i, --fix Apply fixes automatically -q, --quiet Suppress configuration logs低层编码约定
开发指南还列出了如下命名与风格约定:
变量:使用 camelBack 命名(首字母小写,后续单词首字母大写),避免无意义命名,缩写仅首字母大写,不使用前导/尾随下划线(包括m_前缀):
int Height // 错误 string name_of_widget // 错误 int a, b; // 错误 int height; // 正确 string nameOfWidget; // 正确 int height, width; // 正确 CutterJsonWigdet cutterJSONWidget; // 错误 CutterJsonWigdet cutterJsonWigdet; // 正确class Example { private: int index_; // 错误 int m_index; // 错误 int index; // 正确 };匿名命名空间:源文件私有的全局实体(变量、函数、结构体等,即内部链接)应定义在匿名命名空间中:
namespace { int globalCounter = 0; bool doSomething() { ... return true; } };函数:与变量一致使用 camelBack 命名;未使用的参数通过注释掉参数名或直接省略名称的方式处理,避免使用Q_UNUSED:
void do_something() {} // 错误 void DoSomething() {} // 错误 void doSomething() {} // 正确 // 坏:使用 Q_UNUSED void doSomething(int one, int two) { Q_UNUSED(one) ... } // 好:注释掉参数名 void doSomething(int /*one*/, int two) { ... } // 好:省略参数名 void doSomething(int, int two) { ... }类:使用 CamelCase(每个单词首字母大写),缩写仅首字母大写;成员变量遵循变量命名约定(无前导/尾随下划线或m_前缀):
class memory_dock_widget; // 错误 class memoryDockWidget; // 错误 class MemoryDockWidget; // 正确 class CutterJSONWidget // 错误 class CutterJsonWidget // 正确类型转换:避免 C 风格强转,优先使用 C++ 转换(static_cast、const_cast等);对QObject使用qobject_cast。
智能指针:优先使用 C++ 智能指针(unique_ptr、shared_ptr):
RegisterProfileDialog *ui; // 坏 std::unique_ptr<Ui::RegisterProfileDialog> ui; // 好花括号:与 Qt 官方指南不同,Cutter 规定条件语句即使只有一行也必须使用花括号:
// 错误 if (address.isEmpty()) return false; // 正确 if (address.isEmpty()) { return false; } // 错误 for (int i = 0; i < 10; ++i) qDebug("%i", i); // 正确 for (int i = 0; i < 10; ++i) { qDebug("%i", i); }循环:使用 C++11 range-based for:
// 好 - 需要元素副本 for (auto import : importsArray) { doSomething(import); } // 好 - 不需要副本 for (auto &import : importsArray) { doSomething(import); } // 好 - 无需修改 for (const auto &import : importsArray) { doSomething(import); }auto:在迭代器、lambda、类型转换、new初始化等场景优先使用auto:
auto it = myMap.find(key); auto multiply = [](int a, int b) -> int { return a * b; }; auto myFloat = static_cast<float>(myInt); auto *item = new QListWidgetItem(text);nullptr:只使用nullptr,不要使用0或Q_NULLPTR:
std::unique_ptr<QObject> obj = nullptr;连接 Qt 信号的方式
必须使用现代成员函数指针语法连接信号与槽(支持编译期类型检查与 lambda):
// 通常在构造函数中连接当前类的成员 connect(this->ui->button1, &QPushButton::clicked, this, &MyObject::buttonClicked); // 好 // 直接连接其他对象的槽 connect(checkbox, &QCheckBox::toggled, widget, &QWidget::setEnabled); // 好 // 使用 lambda 传递额外参数 connect(button1, &QPushButton::clicked, this, [this](){ foo(getBar()); }); // 好禁止使用旧式宏语法、自动名称连接(如on_actionNew_triggered()槽命名)以及缺少接收对象的 3 参 connect——这些方式可能在运行时静默失效:
// SIGNAL 与 SLOT 宏 connect(sender, SIGNAL(clicked), this, SLOT(buttonClicked)); // 坏 // 自动名称连接 slot: void on_actionNew_triggered(); // 坏 // 缺少接收对象的 3 参数 connect connect(sender, &SomeObject::signal, [this](){ this->foo(getBar()); }); // 坏头文件 include 组织
尽量只在头文件中包含必要的定义,避免引发额外编译;若仅需知道类存在而无需完整原型,可前置声明:
class MyClassThatExists; private: std::unique_ptr<MyClassThatExists> classInstance;然后在.cpp中包含该类头文件。include 顺序为从本地到全局:先引号形式的本地头文件(如#include "common/Helpers.h"),空行后是 Qt 头文件(如#include <QShortcut>),最后是标准 C++ 头文件,且须按字母序排列。这一规则由 clang-format 自动处理(对应 _clang-format 中的IncludeBlocks: Regroup与IncludeCategories配置)。
Doxygen 注释
API 参考文档由 Doxygen 生成,函数文档使用如下格式;仅当函数用途无法从名称直接看出时才需要文档(如getCount()无需注释,syncRemote()应注释):
/** * @brief Add new parameters to the accumulator * @param params The parameters to add * @return True if the parameters were added, false otherwise */ bool accumulate(RefreshDeferrerParams params) { ... };类建议在定义上方加文档,说明其用途:
/** * @brief A short description about SomeDialog */ class SomeDialog { ... };第六步:编写代码、提交 Pull Request
制定实现计划并在对应 Issue 中讨论,动手编码前务必通读本文第五节的编码规范。若不确定如何实现,可参考现有代码中同一组件或类似组件是否实现了相似行为;拷贝现有代码时,思考其为何如此实现——同样的因素未必适用于你的场景,旧代码本身也可能是次优的。
完成代码后,提交变更并遵循 Pull Request 模板打开 PR。模板要求填写Test plan:
- 若进行了 GUI 修改,用截图展示效果;
- 列出评审者用于验证变更符合预期的操作步骤;
- 借此机会考虑潜在的边界情况与不同类型的输入;
- 即使步骤看似琐碎、开发时已执行过,也应完整执行一遍——这有助于发现最终清理阶段引入的错误,并确保没有遗漏。
PR 合并后,还可以继续回到第一步挑选新任务,或者请导师/其他开发者推荐新的 Issue。作为新贡献者,也可以随时向维护者建议改进本文档缺失的信息。
第七步:IDE 开发环境搭建
Cutter 对 IDE 没有硬性要求,任何 CMake 集成良好的 IDE 均可胜任。开发构建默认使用 bundled Rizin(见前文选项表),唯一的例外是打包类工作。src/中大量组件使用.ui文件(XML 格式),Qt Designer 可独立用于可视化编辑,许多编辑器也支持 XML 高亮与代码折叠。
Qt Creator
- 优点:内置 Qt API 帮助、
.ui可视化编辑器(Qt Designer)、调试器中 Qt 类型的显示辅助; - 不足:查看非项目文件(如 Rizin 源码)不便;非 Linux 系统上最简单的安装方式需要 Qt 账号登录。
项目配置:File → Open File or Project...选择cutter/CMakeLists.txt,选择 kit 后点击Configure Project。
clang-format:启用内置 Beautifier 插件,在 clang-format 选项页选择 "Use predefined style: File",即可在保存文件时自动格式化。
修改 CMake 配置:点击左侧 "Projects" 按钮,选择 "Build",所有 CMake 选项可在图形化编辑器中修改。
编辑.ui文件:双击在可视化编辑器中打开;需要按文本编辑时,右键选择Open With → Plain Text Editor。注意从可视化模式切回代码模式会以只读方式打开并提示 "This file can only be edited in Design mode"。
VS Code
- 优点:插件数量庞大;对非项目文件有良好的回退机制;
- 推荐插件:C/C++(微软官方 C++ 支持)、CMake Tools(CMake 项目集成)、CMake(编辑 CMake 文件时的语言支持,与上一插件功能互补,需同时安装)。
项目配置:File → Open Folder...选择克隆目录;安装推荐插件后,CMake Tools 会弹出配置提示,选择[Unspecified]kit;若错过弹窗,可用Ctrl-Shift-P执行CMake: Configure。
修改 CMake 配置:首次配置后,Ctrl-Shift-P执行CMake: Edit CMake Cache,Cutter 相关选项大多以 "CUTTER" 开头。
格式化:C/C++ 扩展内置 clang-format,Ctrl-Shift-I格式化文档,Ctrl-K Ctrl-F仅格式化选区;建议在设置中配置自动格式化。
构建、运行、调试:状态栏与命令面板提供CMake: Build(F7)、CMake: Run Without Debugging(Shift+F5)、CMake Debug(Ctrl+F5)。默认无参启动;需要传参时创建.vscode/launch.json(可从模板Debug: Select and Start Debugging → Add configuration.. → C,C++: (gdb) Launch生成)。
gdb 的 Qt 类型漂亮打印:从 KDevelop 的 gdb printers 脚本下载脚本后,在~/.gdbinit中添加:
python import sys sys.path.insert(0, '/path/to/folder/with/pretty_printer_scripts') from qt import register_qt_printers register_qt_printers (None) end set print pretty 1CLion
- 特点:插件数量中等(许多为 JetBrains 第一方插件);无免费版本;首次打开项目分析文件较慢,.cpp/.h 切换首次可能需要数秒。
项目配置:File → Open选择克隆目录,在左侧文件列表中打开cutter/CMakeLists.txt,点击黄色提示栏中的Load CMake project。
修改 CMake 配置:File → Settings → Build,Execution,Deployment → CMake,与命令行一致使用-DOPTION_NAME=VALUE格式。
编辑.ui文件:默认双击无反应,可拖拽到文本编辑器打开;也可在File → Settings → Editor → File Types中将*.ui关联从Qt UI Designer Form改为 "XML" 或 "Files Opened in Associated Applications"。
Visual Studio
推荐 Visual Studio 2019(CMake 集成最佳);更老版本建议通过命令行或cmake-gui生成 VS 工程再打开。安装时选择 "Desktop development with C++" 组件即可,后续可通过 VS Installer 增删组件。
项目配置:用 VS 打开克隆目录;通过Project → CMake Settings打开 CMake 设置编辑器,勾选所需选项或保持默认;使用 vcpkg 时 VS 会自动检测(也可在CMake toolchain file字段指定 toolchain 路径);不使用 vcpkg 时,在CMake command arguments:字段配置 Qt 路径。为让调试器可读地显示 Qt 类型,可安装 Qt Visual Studio Tools 插件(会生成Documents/Visual Studio 2019/Visualizers/qt6.natvis文件,生成后可卸载插件)。
格式化:VS 默认支持 clang-format,直接使用 Cutter 根目录的_clang-format文件;可通过Tools → Options → Text Editor → C/C++ → Formatting调整触发方式。
编辑.ui文件:默认以 XML 文本打开,可通过右键Open With...配置为 Qt Designer。
进阶话题:Git 子模块与 Rizin 的同步
Rizin 以 git submodule 形式内嵌于 Cutter(rizin/目录),Cutter 需要紧跟 Rizin 的最新版本以获取新特性、bug 修复与性能改进,因此更新子模块是 Cutter 开发中的常见工作。
在 Cutter 根目录查看所有子模块:
git config --file .gitmodules --get-regexp path | awk '{ print $2 }'一次性更新所有子模块:
git submodule foreach git pull origin master git add submodule_name_1 submodule_name_2 git commit -m "Update submodules"多数情况下只需更新 rizin 子模块:
cd rizin git checkout dev && git pull cd .. git add rizin git commit -m "Update rizin submodule"Qt 开发相关资源:若将开发涉及 Qt 的列表/表格类组件,建议阅读 Qt 官方文档中的 Signals & Slots、Model/View Programming、QAction 等专题(可在 Qt 帮助系统中直接查阅)。
结语
Cutter 的贡献流程可以概括为:构建 → 选 Issue → 熟悉现状 → 定位源码 → 按规范编码 → 提交含 Test plan 的 PR → 迭代。其中,通过Core()访问唯一的 CutterCore 实例、用seek()而非cmd("s ...")修改寻址、遵循 camelBack/CamelCase 命名与 clang-format/clang-tidy 工具链约束,是保证代码库一致性的关键。希望这篇指南能帮助你迈出向 Cutter 贡献代码的第一步。
- 应用安全
- 桌面应用
- 开发工具
【免费下载链接】cutter
Free and Open Source Reverse Engineering Platform powered by rizin
相关推荐
note-gen低配笔记实测:流畅吗
note gen低配笔记实测:流畅吗 一句话总评: note gen(本地优先的 AI 笔记应用,Rust + WebView 混合架构)在 4GB 内存的老笔
AI 应用桌面应用移动开发知识管理ChatGPT-Tool-Hub高级玩法:自定义工具开发指南与最佳实践
ChatGPT Tool Hub高级玩法:自定义工具开发指南与最佳实践 ChatGPT Tool Hub是一个强大的开源ChatGPT工具生态系统,让你能够将工
LMCache 贡献指南实战:从环境搭建、测试到代码规范的完整开发流程
LMCache 贡献指南实战:从环境搭建、测试到代码规范的完整开发流程 LMCache 是一个面向大语言模型推理场景的 KV Cache 加速层,通过缓存与管理
人工智能大模型模型推理服务缓存
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考