# oh_tools
**Repository Path**: Cooper0/oh_tools
## Basic Information
- **Project Name**: oh_tools
- **Description**: No description available
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-08-18
- **Last Updated**: 2026-09-30
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 堆栈解析工具
Tauri v2 桌面应用,面向 OpenHarmony/HarmonyOS 开发调试场景,集成堆栈解析、反汇编、HDC 设备操作、本地文件夹并发拷贝等功能。
## 功能概览
| 页面 | 功能 | 说明 |
|------|------|------|
| 文本解析 | 堆栈解行号 | 粘贴堆栈文本,自动提取库名/偏移/BuildId,从 unstrip 目录查找 ELF,调用 llvm-addr2line 解析(含内联帧) |
| 文件解析 | 批量堆栈解析 | 选择含堆栈的文本文件,解析后写回原文件或新文件 |
| 反汇编 | ELF 反汇编 | 选择 ELF 文件,调用 llvm-objdump + llvm-cxxfilt 生成带源码注释的汇编 |
| HDC 工具 | 设备操作 | 连接 HDC 服务器,刷新设备列表,执行预置命令(hilog/selinux/设备信息等),文件推送/拉取 |
| 文件夹拷贝 | 并发拷贝 | 多线程并发拷贝本地文件夹(SMB/本地),实时显示进度,可取消 |
> 同一二进制支持命令行模式:带子命令参数运行时进入 CLI(不启动图形界面),详见 [命令行模式](#命令行模式cli)。
## 技术栈
- **后端**: Rust + Tauri v2(async 命令 + spawn_blocking)
- **前端**: 纯 HTML/CSS/JS(无框架)
- **嵌入工具**: llvm-addr2line / llvm-objdump / llvm-cxxfilt / llvm-readelf(include_bytes! 编译期嵌入,运行时提取)
- **HDC**: hdc_lib_rs(内嵌 hdc 二进制 + libusb)
- **并发拷贝**: threadpool(遍历线程独立于线程池,边遍历边拷贝)
## 平台支持
- **Linux**: x86_64-unknown-linux-gnu(原生编译)
- **Windows**: x86_64-pc-windows-gnu(Linux 交叉编译,mingw 工具链)
## 编译
### 环境准备
```bash
# 1. 安装 Tauri v2 系统依赖(Linux)
sudo apt install -y libwebkit2gtk-4.1-dev libgtk-3-dev libglib2.0-dev librsvg2-dev libsoup-3.0-dev libjavascriptcoregtk-4.1-dev libayatana-appindicator3-dev
# 2. 安装 Tauri CLI
cargo install tauri-cli --version "^2.0"
# 3. 安装 Windows 交叉编译目标
rustup target add x86_64-pc-windows-gnu
# 4. 准备 llvm 工具二进制
./setup-llvm.sh
```
### 编译命令
```bash
./build.sh # 编译 Linux release
./build.sh windows # 交叉编译 Windows release
./build.sh all # 同时编译 Linux + Windows
./build.sh all --debug # 全部用 debug profile
./build.sh all --dist # 编译并打包分发压缩包
./build.sh --help # 帮助菜单
```
### 产物
| 平台 | 路径 | 说明 |
|------|------|------|
| Linux | `target/release/tauri_test` | 单一二进制,内嵌全部工具 |
| Windows | `target/x86_64-pc-windows-gnu/release/tauri_test.exe` | 需同目录放 `WebView2Loader.dll` |
## 堆栈格式支持
### 格式 A(Android/OpenHarmony 风格)
```
#00 pc 000a7d3c /system/lib/ld-musl-arm.so.1(get_meta+92)(e7f9c7b2f43af570ea0042af00f4d899)
```
- 支持函数名含嵌套括号的 C++ 签名(如 `WriteBinder(unsigned long, void*)+66`)
- BuildId 可选,有则校验,无则按 basename 查找
### 格式 B(带 0x 地址 + BuildId 标签)
```
#0 0x651a5c0fa0 (/data/storage/el1/bundle/libs/arm64/libijk.so+0x2c0fa0) (BuildId: 84383086df874d94fa191ddbbc25091cc14992c5)
```
## 命令行模式(CLI)
同一二进制支持双模式:**无参数启动 GUI**;**带子命令参数进入 CLI**(不拉起图形界面,结果输出到 stdout/stderr)。CLI 错误统一用 `anyhow`,带 context 链,退出码非 0。
### 子命令
| 子命令 | 短选项 | 参数(短/长) | 说明 |
|--------|------|------|------|
| `stack-text` | `-s` | `-u/--unstrip
[-i/--input ]` | 解析堆栈文本;省略 `--input` 时从 stdin 读取 |
| `stack-file` | `-f` | `-u/--unstrip -i/--input [-o/--overwrite] [-d/--out-dir ] [-n/--out-name ]` | 批量解析文件并写回 |
| `disasm` | `-d` | `-e/--elf [-p/--prefix ]` | 反汇编 ELF 为 `.asm` |
| `hdc-list` | `-l` | `[-i/--ip ] [-p/--port ]` | 列出 HDC 设备 |
| `hdc-exec` | `-e` | `-d/--device [-i] [-p] -c/--cmd "..."` | 执行 hdc 命令;`-c` 可多次,每条空格分隔 |
| `hdc-config` | `-c` | `-g/--get` 或 `-s/--save ` | 读取/保存 HDC 按钮配置 JSON |
| `hdc-send` | `-n` | `-d/--device -l/--local -r/--remote [-i] [-p]` | 推送文件/文件夹到设备 |
| `hdc-recv` | `-r` | `-d/--device -r/--remote -l/--local [-i] [-p]` | 从设备拉取文件/文件夹 |
| `copy` | `-p` | `-s/--src -d/--dst ` | 本地文件夹并发拷贝,进度刷新到 stderr |
子命令可用短选项触发(程序内部翻译为对应子命令):`-s`/`-f`/`-d`/`-l`/`-e`/`-c`/`-n`/`-r`/`-p`。例 `tauri_test -s -u ` 等同 `tauri_test stack-text -u `。
全局选项:`-v/--verbose` 详细日志(等价 `RUST_LOG=debug`)。
### 示例
```bash
# 从 stdin 解析堆栈
echo "#0 0x0 (/data/lib/libfoo.so+0x1234)" | tauri_test stack-text --unstrip /path/to/unstripped
# 解析文件写回新文件
tauri_test stack-file --unstrip /path/to/unstripped --input crash.txt --out-name crash_parsed.txt
# 反汇编
tauri_test disasm --elf libfoo.so --prefix /source/root
# 列设备 + 执行命令
tauri_test hdc-list
tauri_test hdc-exec --device 123456789 --cmd "shell getenforce" --cmd "shell param get const.product.model"
# 读取/保存配置
tauri_test hdc-config --get > cmd_config.json
tauri_test hdc-config --save cmd_config.json
# 本地文件夹拷贝
tauri_test copy --src /from --dst /to
```
### 退出码
- `0`:成功
- `1`:业务错误(解析失败、文件读写失败、hdc 报错等,错误信息打到 stderr)
- `2`:参数错误(clap 自动处理)
### Windows 控制台说明
Windows release 为 GUI 子系统(双击不弹黑框)。CLI 模式从 cmd/powershell 调用时自动 `AttachConsole(ATTACH_PARENT_PROCESS)` 附加父进程控制台,stdout/stderr 正常输出。父进程无控制台(如资源管理器双击)时输出丢失,但逻辑仍执行,日志落盘到 exe 同目录 `tauri_test_{pid}.log`。Linux 原生正常。
## 项目结构
```
tauri_test/
├── src/ # 前端(HTML/CSS/JS)
│ ├── index.html # 五个 Tab 页面
│ ├── main.js # 事件绑定、invoke 调用
│ └── styles.css # 深色主题
├── src-tauri/ # Rust 后端
│ ├── resources/{linux,windows}/ # 嵌入的 llvm 工具
│ └── src/
│ ├── cli.rs # CLI 子命令(clap)与 Windows 控制台附加
│ ├── commands.rs # async Tauri 命令(薄封装 core)
│ ├── core.rs # 堆栈解析核心逻辑(GUI/CLI 共用)
│ ├── stack_parser.rs # 堆栈解析
│ ├── elf_resolver.rs # ELF 查找 + BuildId 校验
│ ├── addr2line.rs # 解行号(--inlines 保留内联帧)
│ ├── objdump.rs # 反汇编
│ ├── bin_manager.rs # 工具嵌入/提取/子进程管理
│ ├── hdc_tool/ # HDC 设备操作
│ ├── dir_copy/ # 并发文件夹拷贝
│ ├── edge_hide.rs # 窗口靠边吸附隐藏(仅 Windows)
│ └── logger.rs # 日志系统
├── build.sh # 编译脚本
├── setup-llvm.sh # llvm 工具准备
└── plant.md # 设计文档与进展记录
```
## 测试
```bash
cd src-tauri
cargo test --lib # 单元测试
cargo clippy --lib # 代码检查
```
## 依赖
- [Tauri v2](https://v2.tauri.app/) — 桌面应用框架
- [hdc_lib_rs](https://gitee.com/Cooper0/hdc_lib_rs) — HDC 设备通信库
- [threadpool](https://crates.io/crates/threadpool) — 线程池
- [anyhow](https://crates.io/crates/anyhow) — 错误处理
- [clap](https://crates.io/crates/clap) — CLI 参数解析
- [regex](https://crates.io/crates/regex) — 正则表达式
- [log](https://crates.io/crates/log) + [env_logger](https://crates.io/crates/env_logger) — 日志系统,落盘到 exe 同目录
## 插件化(动态库扩展)
框架支持动态库插件,新插件=新页面,C ABI 边界 + SDK 宏封装(开发者无感 CString)。
### 插件开发
1. 新建 crate,`crate-type = ["cdylib"]`,依赖 `plugin-sdk`
2. 实现 `Plugin` trait(`manifest`/`frontend_html`/`frontend_script`/`invoke`)
3. `declare_plugin!(MyPlugin, MyPlugin);` 生成 C ABI 符号
4. `cargo build` 产出 `.so`/`.dll`,放 exe 同级 `plugins/`
5. 重启应用,Tab 自动出现
### 示例
见 `examples/hello-world/`。插件 JS 调 `window.framework.pluginCall(id, cmd, args)` 与后端通信。
### 约束
C ABI 边界,插件可用任意 rustc 编译(跨 rustc 稳定);`plugin_abi_version` 校验 SDK 版本,不符拒载。框架自动调 `plugin_free_str` 防内存泄漏。