# 将 SymCC 替换为 R-Fuzz/SymSan 的代价评估

> 评估对象:把本项目的 concolic 引擎(改造版 SymCC)整体换成 [R-Fuzz/SymSan](https://github.com/R-Fuzz/symsan)
> (基于 LLVM DataFlowSanitizer 的 label 传播式 concolic)。结论先行:**代价高、预期收益低,不建议整体替换。**

---

## 一、一页结论

| | 结论 |
|---|---|
| **总代价** | **≈ 6–10 人周(1.5–2.5 个月)** + 两个真实风险(SymSan 文档未完备、C++ 目标需进程外 FastGen) |
| **收益** | **低**——SymSan 卖点是"求解快/省内存(~10–40×)",而本项目数据已证明**求解吞吐不是覆盖瓶颈** |
| **唯一好消息** | 两边都是 **LLVM 18**,工具链不迁;**编排层 ~90% 可复用**(已把 concolic 当黑盒) |
| **建议** | 不整体替换;若要 SymSan 的速度→低成本把它当 AFL++ 集合里一个额外引擎试水;**真正该做的是优化 showmap 去重/AFL 集成**(数据指向的真瓶颈) |

---

## 二、两个引擎的关键差异

| 维度 | 当前 SymCC(本项目) | R-Fuzz/SymSan |
|---|---|---|
| LLVM 版本 | 18(CMake 接受 8–18) | **18.1.18(未打补丁)** ✅ 同代 |
| 核心机制 | `_sym_*` 符号表达式树 → QSYM → Z3(**108 个 `_sym_*` API**) | **DFSan 影子内存 label 传播 + union-table** |
| 求解 | 进程内 QSYM/Z3 + 自研 fast/multi-solve | 进程内 Z3 **默认关闭、不推荐 C++**;主推**进程外 FastGen**(RGD/JIGSAW) |
| 运行模型 | **二进制自驱**:喂种子→运行时解约束→写 `SYMCC_OUTPUT_DIR`→Python 收编号文件 | **不自产输出**,需 driver(FastGen)或作 **AFL++ custom mutator** |
| C++ 目标 | 支持 | 进程内 Z3 **不推荐 C++**(本项目 FTS/libarchive/freetype2 多为 C++)→ 必须 FastGen |
| 成熟度 | 稳定(本项目已深度改造) | 文档 "still under construction",Linux-amd64 only |

---

## 三、精确代价分解(实测 LOC)

### 引擎层——丢弃 + 重写(代价集中于此)
- **丢弃**:~3,000 行 SymCC 自有 runtime + **~16,800 行 vendored qsym 引擎**(表达式/solver)+ 整个
  LLVM 编译 pass(`compiler/`,100% 替换——SymSan 自带 DFSan pass)。这些是**换掉**,不是移植。
- **真正要在 DFSan 模型上重写的自研逻辑 ≈ 1,170 行**(qsym submodule git diff 实测):

| 技术 | 位置 | ~行 | 是否深嵌引擎 | 移植难度 |
|---|---|---|---|---|
| ① 多分支联合求解 `SYMCC_MULTI_SOLVE` | `solver.cpp:1255–1440` | 300 | 深(遍历 qsym Expr 树按输入字节分组) | **难**(DFSan 只有 label,无表达式树) |
| ② fast-solve `SYMCC_FAST_SOLVE` | `solver.cpp:830–1180` | 350 | 深(贴 qsym Concat/Extract 节点) | **难**;但 FastGen 本身即 JIT 快解→**部分作废** |
| ③ hint 传递 `SYMCC_EMIT_HINTS` | `solver.cpp:144,518,1034` | 40 | 中(需解出的模型字节) | 中 |
| ④ 字典引导 `SYMCC_DICT` | `solver.cpp:544–639` | 100 | 基本独立 | 中/易 |
| ⑤ 选择性符号化 `SYMCC_FOCUS_BYTES` | `qsym/Runtime.cpp:328–403` | 80 | 独立(按输入偏移门控) | **易**(天然映射 DFSan 每字节 taint) |
| 密度剖析 `SYMCC_DENSITY_*` | `solver.cpp:182–215` | 60 | 用 qsym 依赖集 | 中 |
| K-Scheduler `SYMCC_KSCHED` | **纯 Python** | — | 不在引擎 | **免费,原样保留** |
| CacheExprBuilder | `expr_builder.cpp` | — | 上游 qsym hash-consing | 随引擎丢弃(SymSan 自带 label 去重) |

### 编排层——~90% 可复用(唯一大好消息)
`mpi_fuzzing_helper.py`(2,173 行)+ `mpi_concolic_execution.py`(834 行)**已把 concolic 二进制当黑盒**:
```python
# run_symcc_worker: subprocess.run(带 env) → os.scandir(输出目录) 收编号文件 + .hints
env["SYMCC_INPUT_FILE"]=input_file; subprocess.run(["timeout",...]+target_cmd, env=env)
for f in os.scandir(output_dir): ...   # 编号 testcase + <name>.hints
```
MPI 调度、`StreamingShowmap` 去重、位图合并、work-item 切分、K-Scheduler、冗余统计、相位计时——**全部引擎无关,
原样存活**。只要 SymSan 把解写成编号文件落到 `$OUTPUT_DIR`,整个编排器**只需一层薄适配 shim**(重命名 ~7 个
env 变量:`SYMCC_OUTPUT_DIR/EMIT_HINTS/AFL_COVERAGE_MAP/FOCUS_BYTES/...` + 用 SymSan 术语重发/解析 `.hints`)。

### 构建层——全目标重编
9 个微目标 + 全部公开套件(LAVA-M/unibench/google-fts/…)现用 `CC=symcc CXX=sym++` 编;换成 SymSan 的
`KO_CC/KO_CXX`(DFSan wrapper),并改插桩检测符号(`__sym_ctor`→DFSan marker)。**编排很薄,换编译器 + 一个
检测符号即可**;真正的坑是 **C++ 目标必须走 FastGen 进程外求解**。

---

## 四、三个代价桶 + 工时

| 桶 | 内容 | 估计 |
|---|---|---|
| **A. SymSan+FastGen 适配 driver** | 在 SymSan+FastGen 上重建"一个种子→解→编号文件落目录"的 SymCC 契约(**复用 90% 编排的前提**);C++ 目标接 FastGen | **1.5–2.5 周** |
| **B. 重写 ①–⑤** | ⑤易 / ④③中 / **①②难**(②可直接用 FastGen 原生快解、放弃自研) | **3–5 周** |
| **C. 全目标重编 + 验证** | `KO_CC` 重编、改检测符号、C++ 调通、全套 benchmark 重跑重新调参 | **2–3 周** |
| | **合计** | **≈ 6–10 人周** |

---

## 五、战略判断(最该看的一条)

SymSan 的核心优势是**求解更快、更省内存(~10–40×)**——但**本项目本轮实测已证明:求解吞吐不是覆盖率瓶颈。**
- **#1 干净消融**:增强让 SymCC 生成量 ×12(MPI tc/s 498→5,856)→ libarchive 覆盖 **+0pp**;
- **D5③ 相位计时**:worker 时间大头是 **showmap 去重**(np=32 占 **53%**),不是 Z3 求解(占 46%,且随 np 下降);
- **D1/D5 扩展曲线**:并行度过 **~64** 就冗余递减,吞吐/覆盖双双回落。

→ **SymSan 优化的正是被本项目数据证明"不卡"的环节**(求解速度/内存)。除非目标转向"每核更省内存以塞更多 worker"
(而 D1 显示 >64 worker 已收益递减),否则大改的**边际覆盖收益预期极低**。

---

## 六、建议

1. **不建议整体替换**——高代价(6–10 周,含研究核心 ①② 重写)、低预期收益(所优化非瓶颈)。
2. 若确实想要 SymSan 的省内存/速度:**低成本试水**——SymSan 是 AFL++ custom mutator,可作**集合里一个额外引擎**
   与现 SymCC 并列(不动你的 5 个技术),先量它带来多少覆盖增量再决定。(注:集合天花板本就有限。)
3. **真正划算的方向**:照数据走,优化 **showmap 去重 / AFL 集成**(D5③ 指向的真瓶颈)——见随附的
   `showmap_dedup_优化.md`(已在做)。
