diff --git a/driver/CMakeLists.txt b/driver/CMakeLists.txt
index 0a2b4c0..54fcb45 100644
--- a/driver/CMakeLists.txt
+++ b/driver/CMakeLists.txt
@@ -18,6 +18,25 @@ target_link_libraries(FGTest PRIVATE
 )
 install (TARGETS FGTest DESTINATION ${SYMSAN_BIN_DIR})
 
+## RGD/JIGSAW-backed one-shot driver (SOTA solver cascade: I2S -> JIGSAW -> Z3)
+add_executable(FGTestRGD fgtest_rgd.cpp)
+set_target_properties(FGTestRGD PROPERTIES OUTPUT_NAME "fgtest_rgd")
+target_compile_options(FGTestRGD PRIVATE -mcx16 -march=native)
+target_include_directories(FGTestRGD PUBLIC
+    ${CMAKE_CURRENT_SOURCE_DIR}/../runtime
+)
+target_link_libraries(FGTestRGD PRIVATE
+  launcher
+  rgd-parser
+  rgd-solver
+  jigsaw
+  ${Z3_LIBRARY}
+  tcmalloc
+  profiler
+  rt
+)
+install (TARGETS FGTestRGD DESTINATION ${SYMSAN_BIN_DIR})
+
 if (DEFINED AFLPP_PATH)
     add_subdirectory(aflpp)
 endif()
diff --git a/driver/fgtest.cpp b/driver/fgtest.cpp
index 510f5a1..eebdac6 100644
--- a/driver/fgtest.cpp
+++ b/driver/fgtest.cpp
@@ -11,7 +11,10 @@ extern "C" {
 #include "parse-z3.h"
 
 #include <algorithm>
+#include <fstream>
+#include <map>
 #include <memory>
+#include <string>
 #include <unordered_map>
 #include <unordered_set>
 #include <utility>
@@ -43,6 +46,7 @@ static size_t input_size;
 
 // for output
 static const char* __output_dir = ".";
+static char* __focus_spec = nullptr;  // 选择性符号化区间规格,待 symsan_init 之后下发
 static uint32_t __instance_id = 0;
 static uint32_t __session_id = 0;
 static uint32_t __current_index = 0;
@@ -52,6 +56,99 @@ static z3::context __z3_context;
 // z3parser
 symsan::Z3ParserSolver *__z3_parser = nullptr;
 
+// ============ 技术③ 字典引导 + 技术① 多字段解组合 ============
+// 均移植自 SymCC 的 qsym solver.cpp,在 driver 层实现(不触碰 DFSan 运行时/rgd 求解器)。
+// 经 getenv 读 SYMCC_DICT / SYMCC_MULTI_SOLVE——与 SymCC 同名通道,编排层的策略档已下发,
+// SymSanEngine.wrap_run 原样透传环境变量给 fgtest,故无需额外接线。
+static std::vector<std::vector<uint8_t>> __dict_tokens;  // ③ AFL 字典 token 列表
+static bool __multi_solve = false;                       // ① SYMCC_MULTI_SOLVE>=1 时启用
+static std::map<size_t, uint8_t> __combined_sets;        // ① 累积各分支的 SET 解(offset->val)
+static bool __emit_hints = false;                        // ② SYMCC_EMIT_HINTS 时写 .hints 旁车
+
+// 把一段字节写成一个编号 id-* 输出(求解结果 / dict 变体 / combined 输入复用同一出口),
+// 返回写出的文件路径(空串=失败),供 ② hint 旁车文件复用同一文件名。
+static std::string write_output(const std::vector<uint8_t>& data, const char* tag) {
+  char path[PATH_MAX];
+  snprintf(path, PATH_MAX, "%s/id-%d-%d-%d", __output_dir,
+           __instance_id, __session_id, __current_index++);
+  int fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
+  if (fd == -1) { AOUT("failed to open %s output\n", tag); return std::string(); }
+  if (write(fd, data.data(), data.size()) == -1)
+    AOUT("failed to write %s output\n", tag);
+  close(fd);
+  return std::string(path);
+}
+
+// ② hint 传递(移植自 SymCC saveValues 的 emit_hints 段):给某个求解输出写 .hints 旁车,
+//    每行 "offset:old:new"(十六进制)记录相对原始种子改动的字节。编排层
+//    (mpi_fuzzing_helper 读 *.hints → hint_map)据此做精准变异 / focus_bytes。
+static void emit_hints(const std::string& path, const std::vector<uint8_t>& out) {
+  if (!__emit_hints || path.empty()) return;
+  std::ofstream hf(path + ".hints");
+  if (!hf.is_open()) return;
+  char buf[64];
+  for (size_t i = 0; i < out.size() && i < input_size; i++) {
+    if (out[i] != (uint8_t)input_buf[i]) {
+      snprintf(buf, sizeof(buf), "%zu:%02x:%02x\n", i,
+               (uint8_t)input_buf[i], out[i]);
+      hf << buf;
+    }
+  }
+}
+
+// ③ 载入 AFL 字典(SYMCC_DICT):格式 "token" 或 name="token",支持 \xNN 转义。
+//    复刻 SymCC Solver::loadDictionary。
+static void load_dictionary() {
+  const char* dict_path = getenv("SYMCC_DICT");
+  if (!dict_path) return;
+  std::ifstream ifs(dict_path);
+  if (ifs.fail()) { AOUT("cannot open dict %s\n", dict_path); return; }
+  std::string line;
+  while (std::getline(ifs, line)) {
+    size_t s = line.find('"'), e = line.rfind('"');
+    if (s == std::string::npos || e == std::string::npos || s >= e) continue;
+    std::string t = line.substr(s + 1, e - s - 1);
+    std::vector<uint8_t> token;
+    for (size_t i = 0; i < t.size(); i++) {
+      if (t[i] == '\\' && i + 3 < t.size() && t[i + 1] == 'x') {
+        char hex[3] = {t[i + 2], t[i + 3], '\0'};
+        token.push_back((uint8_t)strtol(hex, NULL, 16));
+        i += 3;
+      } else {
+        token.push_back((uint8_t)t[i]);
+      }
+    }
+    if (!token.empty()) __dict_tokens.push_back(token);
+  }
+  AOUT("loaded %zu dict tokens from %s\n", __dict_tokens.size(), dict_path);
+}
+
+// ③ 对 Z3 求解改动的【首个】字节位置,用字典 token 拼接生成额外变体(cap 20)。
+//    从原始种子出发(非求解结果),跳过与原值/解相同的 token。复刻 SymCC saveDictVariants。
+static void save_dict_variants(const std::vector<uint8_t>& solved) {
+  if (__dict_tokens.empty()) return;
+  size_t first = SIZE_MAX;
+  for (size_t i = 0; i < solved.size() && i < input_size; i++)
+    if (solved[i] != (uint8_t)input_buf[i]) { first = i; break; }
+  if (first == SIZE_MAX) return;
+  int variants = 0;
+  const int kMaxDictVariants = 20;
+  for (const auto& token : __dict_tokens) {
+    if (variants >= kMaxDictVariants) break;
+    if (first + token.size() > input_size) continue;
+    bool same_orig = true, same_solved = true;
+    for (size_t j = 0; j < token.size(); j++) {
+      if (token[j] != (uint8_t)input_buf[first + j]) same_orig = false;
+      if (first + j < solved.size() && token[j] != solved[first + j]) same_solved = false;
+    }
+    if (same_orig || same_solved) continue;
+    std::vector<uint8_t> variant(input_buf, input_buf + input_size);
+    for (size_t j = 0; j < token.size(); j++) variant[first + j] = token[j];
+    write_output(variant, "dict");
+    variants++;
+  }
+}
+
 static void generate_input(symsan::Z3ParserSolver::solution_t &solutions) {
   using op_t = symsan::Z3ParserSolver::solution_op_t;
 
@@ -96,24 +193,37 @@ static void generate_input(symsan::Z3ParserSolver::solution_t &solutions) {
     }
   }
 
-  // Write the new input to file
-  char path[PATH_MAX];
-  snprintf(path, PATH_MAX, "%s/id-%d-%d-%d", __output_dir,
-           __instance_id, __session_id, __current_index++);
-  int fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
-  if (fd == -1) {
-    AOUT("failed to open new input file for write");
-    return;
+  // ① 多字段解组合:累积本分支的 SET 解(offset->val,后写覆盖)。运行结束时若累积到 >=2
+  //    个不同偏移,额外产出一个"同时满足全部字段"的组合输入(见 flush_combined_input)。
+  if (__multi_solve) {
+    for (const auto& sol : solutions)
+      if (sol.op == op_t::SET && sol.offset < input_size)
+        __combined_sets[sol.offset] = sol.val;
   }
 
+  // Write the new input to file
   AOUT("generate #%d output (size: %zu -> %zu)\n",
-       __current_index - 1, input_size, new_input.size());
+       __current_index, input_size, new_input.size());
+  std::string path = write_output(new_input, "sol");
+  emit_hints(path, new_input);  // ② 写 offset:old:new 旁车,供编排层精准变异
 
-  if (write(fd, new_input.data(), new_input.size()) == -1) {
-    AOUT("failed to write new input\n");
-  }
+  // ③ 字典引导:对本次求解改动的首个位置拼接字典 token,产出额外变体
+  save_dict_variants(new_input);
+}
 
-  close(fd);
+// ① 运行结束时把累积的各分支 SET 解合并成一个输入(多字段一次全满足)。SymSan 的
+//    求解器按 task 逐分支求解,故这里在【解层面】组合,达到 SymCC negateGroup 联合求解
+//    同样的效果:一次跨过多字段校验,省去逐字段反馈迭代。各偏移互斥 → 组合无冲突;结果
+//    是候选输入,由覆盖反馈确认(sound)。
+static void flush_combined_input() {
+  if (!__multi_solve || __combined_sets.size() < 2) return;
+  std::vector<uint8_t> merged(input_buf, input_buf + input_size);
+  for (const auto& kv : __combined_sets)
+    if (kv.first < merged.size()) merged[kv.first] = kv.second;
+  AOUT("multi-solve: combined %zu field solutions into one input\n",
+       __combined_sets.size());
+  std::string path = write_output(merged, "combined");
+  emit_hints(path, merged);  // ② 组合输出同样写 hint 旁车
 }
 
 static void __solve_cond(dfsan_label label, uint8_t r, bool add_nested, void *addr) {
@@ -204,6 +314,18 @@ int main(int argc, char* const argv[]) {
         is_stdin = 1;
     }
 
+    // 选择性符号化:解析 focus_bytes(如 "0-3" 或 "0-3,8-11")。注意 symsan_init 会
+    // 重置 g_config,故此处仅把规格暂存到 fgtest 自己的静态变量,待 init 之后再下发。
+    char *focus = strstr(options, "focus_bytes=");
+    if (focus) {
+      focus += strlen("focus_bytes=");
+      char *end = strchr(focus, ':');
+      if (end == NULL) end = strchr(focus, ' ');
+      size_t n = end == NULL ? strlen(focus) : (size_t)(end - focus);
+      if (n > 0)
+        __focus_spec = strndup(focus, n);
+    }
+
     // check for debug
     char *debug_opt = strstr(options, "debug=");
     if (debug_opt) {
@@ -236,6 +358,11 @@ int main(int argc, char* const argv[]) {
     }
   }
 
+  // 技术③/②/① 开关(与 SymCC 同名环境变量,经 fgtest 自身 env 直接读取):
+  __multi_solve = getenv("SYMCC_MULTI_SOLVE") != nullptr;  // ① 多字段解组合
+  __emit_hints = getenv("SYMCC_EMIT_HINTS") != nullptr;    // ② hint 旁车文件
+  load_dictionary();                                       // ③ 载入 SYMCC_DICT 字典
+
   // load input file
   struct stat st;
   int input_fd = open(input, O_RDONLY);
@@ -273,8 +400,14 @@ int main(int argc, char* const argv[]) {
   }
 
   symsan_set_debug(debug);
-  symsan_set_bounds_check(1);
+  // "遇内存错误即退出"纯为内存错误检测,concolic 求解不需要,反而有害:目标合法的未初始化
+  // 内存访问会在 bounds/GEP 追踪里产生 kInitializingLabel → 提前 Die() → 丢大量产出。实测默认关掉后
+  // 各目标严格更优(base64 28→56、pcre2 140→488、xml 不变、sqlite 0→42)。故【默认关】,
+  // SYMSAN_MEMERR_EXIT=1 可恢复。bounds 追踪保留(供 GEP/数组下标求解);SYMSAN_NO_BOUNDS 可关。
+  symsan_set_bounds_check(getenv("SYMSAN_NO_BOUNDS") ? 0 : 1);
+  symsan_set_exit_on_memerror(getenv("SYMSAN_MEMERR_EXIT") ? 1 : 0);
   symsan_set_solve_ub(solve_ub);
+  symsan_set_focus_bytes(__focus_spec);  // 选择性符号化(init 之后下发,避免被重置)
 
   // launch the target
   int ret = symsan_run(input_fd);
@@ -355,6 +488,8 @@ int main(int argc, char* const argv[]) {
     }
   }
 
+  flush_combined_input();  // ① 事件循环结束后产出多字段组合输入
+
   symsan_destroy();
   exit(0);
 }
diff --git a/driver/fgtest_rgd.cpp b/driver/fgtest_rgd.cpp
new file mode 100644
index 0000000..4420c59
--- /dev/null
+++ b/driver/fgtest_rgd.cpp
@@ -0,0 +1,363 @@
+// fgtest_rgd:RGD/JIGSAW 后端的 one-shot concolic driver。
+//
+// 与 fgtest.cpp(进程内 Z3,Z3ParserSolver)的区别:改用 SymSan 的 SOTA 求解栈
+// (RGDAstParser + I2SSolver→(JITSolver)→Z3Solver 级联,源自 R-Fuzz/SymSan 的 AFL++
+// custom-mutator 参考实现 driver/aflpp/symsan.cpp)。契约相同:读一个种子文件、跑目标、
+// 把每个求出的新输入写进 TAINT_OPTIONS 的 output_dir/id-*,故编排层可原样复用。
+//
+// 求解级联(每个 task 依次尝试,命中即止):
+//   I2SSolver —— input-to-state(RedQueen 式),直接把比较操作数回写到输入,cheap,专治
+//                magic/校验和;
+//   JITSolver —— JIGSAW 梯度求解(可选,SYMSAN_USE_JIGSAW;需 LLVM JIT);
+//   Z3Solver  —— SMT 兜底,保证不弱于 fgtest 的 Z3 基线。
+//
+// 复用移植的自研技术:④选择性符号化(运行时 get_label_for 门控,经 focus_bytes 透传)、
+// ③字典引导(SYMCC_DICT)、②hint(SYMCC_EMIT_HINTS)。①多字段解组合对"整缓冲输出"的
+// RGD 解意义不大(I2S 本就整体求解),此 driver 不含。
+#include "defs.h"
+#include "debug.h"
+#include "version.h"
+
+#include "dfsan/dfsan.h"
+
+extern "C" {
+#include "launch.h"
+}
+
+#include "parse-rgd.h"
+#include "cov.h"
+#include "task_mgr.h"
+#include "solver.h"
+
+#include <fstream>
+#include <map>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+using namespace __dfsan;
+
+#undef AOUT
+#define AOUT(...)                                       \
+  do {                                                  \
+    if (__debug) printf(__VA_ARGS__);                   \
+  } while (false)
+
+// ---- input / output 全局 ----
+static char *input_buf;
+static size_t input_size;
+static const char *__output_dir = ".";
+static char *__focus_spec = nullptr;   // ④ 待 symsan_init 之后下发
+static uint32_t __instance_id = 0;
+static uint32_t __session_id = 0;
+static uint32_t __current_index = 0;
+static int __debug = 0;
+static uint8_t *__out_buf = nullptr;    // RGD 求解器写整个新输入到此
+static const size_t kMaxOut = 1u << 20; // 1 MiB 输出上界
+
+// ---- 技术③/② 全局 ----
+static std::vector<std::vector<uint8_t>> __dict_tokens;  // ③ AFL 字典
+static bool __emit_hints = false;                        // ② .hints 旁车
+
+// ---- RGD 求解栈 ----
+// 求解器(i2s)需要 __dfsan::get_label_info 索引 shm 里的 union table;driver 侧提供
+// (与 aflpp/symsan.cpp 一致)。base 在 symsan_init 之后设。
+static dfsan_label_info *__label_info_base = nullptr;
+static size_t __max_label = 0;
+namespace __dfsan {
+dfsan_label_info *get_label_info(dfsan_label label) {
+  if (label >= __max_label)
+    throw std::out_of_range("label too large " + std::to_string(label));
+  return &__label_info_base[label];
+}
+}  // namespace __dfsan
+
+static rgd::RGDAstParser *__parser = nullptr;
+static rgd::TaskManager *__task_mgr = nullptr;
+static rgd::CovManager *__cov_mgr = nullptr;
+static std::vector<std::shared_ptr<rgd::Solver>> __solvers;
+
+// 把一段字节写成一个编号 id-* 输出,返回路径(空=失败),供 ② hint 旁车复用文件名。
+static std::string write_output(const uint8_t *data, size_t len, const char *tag) {
+  char path[PATH_MAX];
+  snprintf(path, PATH_MAX, "%s/id-%d-%d-%d", __output_dir,
+           __instance_id, __session_id, __current_index++);
+  int fd = open(path, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
+  if (fd == -1) { AOUT("failed to open %s output\n", tag); return std::string(); }
+  if (write(fd, data, len) == -1)
+    AOUT("failed to write %s output\n", tag);
+  close(fd);
+  return std::string(path);
+}
+
+// ② hint:写 offset:old:new 旁车(相对种子的改动字节)
+static void emit_hints(const std::string &path, const uint8_t *out, size_t len) {
+  if (!__emit_hints || path.empty()) return;
+  std::ofstream hf(path + ".hints");
+  if (!hf.is_open()) return;
+  char buf[64];
+  for (size_t i = 0; i < len && i < input_size; i++) {
+    if (out[i] != (uint8_t)input_buf[i]) {
+      snprintf(buf, sizeof(buf), "%zu:%02x:%02x\n", i, (uint8_t)input_buf[i], out[i]);
+      hf << buf;
+    }
+  }
+}
+
+// ③ 载入 AFL 字典(SYMCC_DICT)
+static void load_dictionary() {
+  const char *dict_path = getenv("SYMCC_DICT");
+  if (!dict_path) return;
+  std::ifstream ifs(dict_path);
+  if (ifs.fail()) return;
+  std::string line;
+  while (std::getline(ifs, line)) {
+    size_t s = line.find('"'), e = line.rfind('"');
+    if (s == std::string::npos || e == std::string::npos || s >= e) continue;
+    std::string t = line.substr(s + 1, e - s - 1);
+    std::vector<uint8_t> token;
+    for (size_t i = 0; i < t.size(); i++) {
+      if (t[i] == '\\' && i + 3 < t.size() && t[i + 1] == 'x') {
+        char hex[3] = {t[i + 2], t[i + 3], '\0'};
+        token.push_back((uint8_t)strtol(hex, NULL, 16));
+        i += 3;
+      } else {
+        token.push_back((uint8_t)t[i]);
+      }
+    }
+    if (!token.empty()) __dict_tokens.push_back(token);
+  }
+  AOUT("loaded %zu dict tokens\n", __dict_tokens.size());
+}
+
+// ③ 对求解改动的首个位置拼字典 token 产变体(cap 20),从种子出发
+static void save_dict_variants(const uint8_t *solved, size_t len) {
+  if (__dict_tokens.empty()) return;
+  size_t first = SIZE_MAX;
+  for (size_t i = 0; i < len && i < input_size; i++)
+    if (solved[i] != (uint8_t)input_buf[i]) { first = i; break; }
+  if (first == SIZE_MAX) return;
+  int variants = 0;
+  const int kMaxDictVariants = 20;
+  for (const auto &token : __dict_tokens) {
+    if (variants >= kMaxDictVariants) break;
+    if (first + token.size() > input_size) continue;
+    bool same_orig = true, same_solved = true;
+    for (size_t j = 0; j < token.size(); j++) {
+      if (token[j] != (uint8_t)input_buf[first + j]) same_orig = false;
+      if (first + j < len && token[j] != solved[first + j]) same_solved = false;
+    }
+    if (same_orig || same_solved) continue;
+    std::vector<uint8_t> variant(input_buf, input_buf + input_size);
+    for (size_t j = 0; j < token.size(); j++) variant[first + j] = token[j];
+    write_output(variant.data(), variant.size(), "dict");
+    variants++;
+  }
+}
+
+// 一个求出的新输入:写主输出 + hint + 字典变体
+static void emit_solution(const uint8_t *out, size_t len) {
+  std::string path = write_output(out, len, "sol");
+  emit_hints(path, out, len);
+  save_dict_variants(out, len);
+}
+
+// 事件:条件分支 → 解析成 tasks 入队(镜像 aflpp handle_cond)
+static void handle_cond(pipe_msg &msg) {
+  if (msg.label == 0) return;
+  bool always_solve = (msg.flags & F_ADD_CONS) == 0;
+  bool loop_latch = (msg.flags & F_LOOP_LATCH) != 0;
+  bool loop_exit = (msg.flags & F_LOOP_EXIT) != 0;
+
+  auto ctx = __cov_mgr->add_branch((void *)msg.addr, msg.id, msg.result != 0,
+                                   msg.context, loop_latch, loop_exit);
+  auto neg_ctx = std::make_shared<rgd::BranchContext>();
+  *neg_ctx = *ctx;
+  neg_ctx->direction = !ctx->direction;
+
+  if (__cov_mgr->is_branch_interesting(neg_ctx) || always_solve) {
+    std::vector<uint64_t> tasks;
+    if (__parser->parse_cond(msg.label, ctx->direction, msg.flags & F_ADD_CONS, tasks) != 0)
+      return;
+    for (auto const &tid : tasks) {
+      auto task = __parser->retrieve_task(tid);
+      if (task) __task_mgr->add_task(neg_ctx, task);
+    }
+  }
+}
+
+// 事件:符号 GEP 索引 → 解析成 tasks 入队(镜像 aflpp handle_gep)
+static void handle_gep(gep_msg &gmsg, pipe_msg &msg) {
+  if (msg.label == 0) return;
+  std::vector<uint64_t> tasks;
+  if (__parser->parse_gep(gmsg.ptr_label, gmsg.ptr, gmsg.index_label, gmsg.index,
+                          gmsg.num_elems, gmsg.elem_size, gmsg.current_offset,
+                          false, tasks) != 0)
+    return;
+  auto ctx = std::make_shared<rgd::BranchContext>();
+  ctx->addr = (void *)msg.addr;
+  ctx->direction = true;
+  for (auto const &tid : tasks) {
+    auto task = __parser->retrieve_task(tid);
+    if (task) __task_mgr->add_task(ctx, task);
+  }
+}
+
+// 事件循环后:抽干任务队列,每个 task 走求解级联,命中即写输出
+static void solve_all_tasks() {
+  size_t solved = 0;
+  for (auto task = __task_mgr->get_next_task(); task; task = __task_mgr->get_next_task()) {
+    for (auto &solver : __solvers) {
+      size_t out_size = 0;
+      auto r = solver->solve(task, (const uint8_t *)input_buf, input_size,
+                             __out_buf, out_size);
+      if (r == rgd::SOLVER_SAT && out_size > 0) {
+        emit_solution(__out_buf, out_size);
+        solved++;
+        break;  // 命中即止,进入下一个 task
+      }
+    }
+  }
+  AOUT("solved %zu tasks\n", solved);
+}
+
+int main(int argc, char *const argv[]) {
+  if (argc != 3) {
+    fprintf(stderr, "Usage: %s target input\n", argv[0]);
+    exit(1);
+  }
+  char *program = argv[1];
+  char *input = argv[2];
+
+  int is_stdin = 0;
+  int solve_ub = 0;
+  bool use_jigsaw = getenv("SYMSAN_USE_JIGSAW") != nullptr;  // 可选 JIGSAW 梯度求解
+  bool nested = getenv("SYMSAN_USE_NESTED") != nullptr;
+
+  char *options = getenv("TAINT_OPTIONS");
+  if (options) {
+    char *output = strstr(options, "output_dir=");
+    if (output) {
+      output += 11;
+      char *end = strchr(output, ':');
+      if (end == NULL) end = strchr(output, ' ');
+      size_t n = end == NULL ? strlen(output) : (size_t)(end - output);
+      __output_dir = strndup(output, n);
+    }
+    char *taint_file = strstr(options, "taint_file=");
+    if (taint_file) {
+      taint_file += strlen("taint_file=");
+      char *end = strchr(taint_file, ':');
+      if (end == NULL) end = strchr(taint_file, ' ');
+      size_t n = end == NULL ? strlen(taint_file) : (size_t)(end - taint_file);
+      if (n == 5 && !strncmp(taint_file, "stdin", 5)) is_stdin = 1;
+    }
+    // ④ 选择性符号化 focus_bytes(暂存,init 后下发)
+    char *focus = strstr(options, "focus_bytes=");
+    if (focus) {
+      focus += strlen("focus_bytes=");
+      char *end = strchr(focus, ':');
+      if (end == NULL) end = strchr(focus, ' ');
+      size_t n = end == NULL ? strlen(focus) : (size_t)(end - focus);
+      if (n > 0) __focus_spec = strndup(focus, n);
+    }
+    char *debug_opt = strstr(options, "debug=");
+    if (debug_opt && (debug_opt[6] == '1')) __debug = 1;
+    if (strstr(options, "solve_ub=1")) solve_ub = 1;
+  }
+
+  __emit_hints = getenv("SYMCC_EMIT_HINTS") != nullptr;  // ②
+  load_dictionary();                                     // ③
+
+  // load input file (mmap,污点源)
+  struct stat st;
+  int input_fd = open(input, O_RDONLY);
+  if (input_fd == -1) { fprintf(stderr, "open input: %s\n", strerror(errno)); exit(1); }
+  fstat(input_fd, &st);
+  input_size = st.st_size;
+  input_buf = (char *)mmap(NULL, input_size, PROT_READ, MAP_PRIVATE, input_fd, 0);
+  if (input_buf == (void *)-1) { fprintf(stderr, "mmap input\n"); exit(1); }
+
+  __out_buf = (uint8_t *)malloc(kMaxOut);
+  if (!__out_buf) { fprintf(stderr, "alloc out buf\n"); exit(1); }
+
+  // setup launcher + 运行目标
+  void *shm_base = symsan_init(program, uniontable_size);
+  if (shm_base == (void *)-1) { fprintf(stderr, "map shm\n"); exit(1); }
+  __label_info_base = (dfsan_label_info *)shm_base;   // get_label_info 索引基址
+  __max_label = uniontable_size / sizeof(dfsan_label_info);
+  if (symsan_set_input(is_stdin ? "stdin" : input) != 0) { fprintf(stderr, "set input\n"); exit(1); }
+  char *args[3] = {program, input, NULL};
+  if (symsan_set_args(2, args) != 0) { fprintf(stderr, "set args\n"); exit(1); }
+  symsan_set_debug(__debug);
+  // "遇内存错误即退出"对 concolic 有害:目标合法的未初始化内存访问会在 bounds/GEP 追踪里
+  // 产生 kInitializingLabel → 提前 Die() → 丢大量产出。默认关掉严格更优(见 fgtest.cpp 注)。
+  // SYMSAN_MEMERR_EXIT=1 恢复;bounds 保留(GEP 求解),SYMSAN_NO_BOUNDS 可关。
+  symsan_set_bounds_check(getenv("SYMSAN_NO_BOUNDS") ? 0 : 1);
+  symsan_set_exit_on_memerror(getenv("SYMSAN_MEMERR_EXIT") ? 1 : 0);
+  symsan_set_solve_ub(solve_ub);
+  symsan_set_focus_bytes(__focus_spec);  // ④ init 之后下发
+
+  int ret = symsan_run(input_fd);
+  if (ret != 0) { fprintf(stderr, "launch target: %d\n", ret); exit(1); }
+  close(input_fd);
+
+  // setup RGD 解析器 + 覆盖管理 + 任务队列 + 求解级联
+  __parser = new rgd::RGDAstParser(shm_base, uniontable_size, nested, 200);
+  __cov_mgr = new rgd::EdgeCovManager();
+  __task_mgr = new rgd::FIFOTaskManager();
+  __solvers.emplace_back(std::make_shared<rgd::I2SSolver>());  // input-to-state 先行
+  if (use_jigsaw)
+    __solvers.emplace_back(std::make_shared<rgd::JITSolver>()); // JIGSAW(可选)
+  __solvers.emplace_back(std::make_shared<rgd::Z3Solver>());   // SMT 兜底(保证不弱于 Z3 基线)
+
+  std::vector<symsan::input_t> inputs;
+  inputs.push_back({(uint8_t *)input_buf, input_size});
+  if (__parser->restart(inputs) != 0) { fprintf(stderr, "parser restart\n"); exit(1); }
+
+  // 事件循环:构造求解任务
+  pipe_msg msg;
+  gep_msg gmsg;
+  size_t msg_size;
+  memcmp_msg *mmsg = nullptr;
+  while (symsan_read_event(&msg, sizeof(msg), 0) > 0) {
+    switch (msg.msg_type) {
+      case cond_type:
+        handle_cond(msg);
+        break;
+      case gep_type:
+        if (symsan_read_event(&gmsg, sizeof(gmsg), 0) != sizeof(gmsg)) break;
+        if (msg.label != gmsg.index_label) break;
+        handle_gep(gmsg, msg);
+        break;
+      case memcmp_type:
+        if (!msg.flags) break;  // 双符号操作数,无内容可读
+        msg_size = sizeof(memcmp_msg) + msg.result;
+        mmsg = (memcmp_msg *)malloc(msg_size);
+        if (symsan_read_event(mmsg, msg_size, 0) != (ssize_t)msg_size) { free(mmsg); break; }
+        if (msg.label != mmsg->label) { free(mmsg); break; }
+        __parser->record_memcmp(msg.label, mmsg->content, msg.result);  // 喂 I2S
+        free(mmsg);
+        break;
+      default:
+        break;
+    }
+  }
+
+  // 抽干任务队列 → 求解 → 写输出
+  solve_all_tasks();
+
+  symsan_destroy();
+  exit(0);
+}
diff --git a/driver/launcher/launch.c b/driver/launcher/launch.c
index b7e207d..c2d3080 100644
--- a/driver/launcher/launch.c
+++ b/driver/launcher/launch.c
@@ -50,6 +50,7 @@ struct symsan_config {
   int exit_on_memerror;
   int trace_file_size;
   int force_stdin;
+  char *focus_bytes;  // 选择性符号化:仅污染这些输入偏移(如 "0-3"),NULL/空=全部
 
   int dev_null_fd;
 
@@ -86,6 +87,7 @@ void* symsan_init(const char *symsan_bin, const size_t uniontable_size) {
   g_config.exit_on_memerror = 1;
   g_config.trace_file_size = 0;
   g_config.force_stdin = 0;
+  g_config.focus_bytes = NULL;
   g_config.dev_null_fd = -1;
   g_config.exit_status = 0;
   g_config.is_killed = 0;
@@ -218,6 +220,14 @@ int symsan_set_force_stdin(int enable) {
   return 0;
 }
 
+__attribute__((visibility("default")))
+int symsan_set_focus_bytes(const char *spec) {
+  // 选择性符号化区间规格,如 "0-3" 或 "0-3,8-11";NULL/空串=符号化全部字节。
+  free(g_config.focus_bytes);
+  g_config.focus_bytes = (spec && spec[0]) ? strdup(spec) : NULL;
+  return 0;
+}
+
 __attribute__((visibility("default")))
 int symsan_run(int fd) {
   if (fd < 0) {
@@ -256,14 +266,21 @@ int symsan_run(int fd) {
     return SYMSAN_NO_MEMORY;
   }
 
+  // 选择性符号化:仅当配置了 focus_bytes 才追加该段(空段避免设成空标志)
+  char focus_seg[512];
+  focus_seg[0] = '\0';
+  if (g_config.focus_bytes && g_config.focus_bytes[0]) {
+    snprintf(focus_seg, sizeof(focus_seg), ":focus_bytes=%s", g_config.focus_bytes);
+  }
+
   // fds and configs could have been changed, so always set up new ones
   g_config.symsan_env = alloc_printf(
       "taint_file=\"%s\":shm_fd=%d:pipe_fd=%d:debug=%d:trace_bounds=%d:"
-      "solve_ub=%d:exit_on_memerror=%d:trace_fsize=%d:force_stdin=%d",
+      "solve_ub=%d:exit_on_memerror=%d:trace_fsize=%d:force_stdin=%d%s",
       g_config.input_file, g_config.shm_fd, g_config.pipefds[1],
       g_config.enable_debug, g_config.enable_bounds_check,
       g_config.enable_solve_ub, g_config.exit_on_memerror,
-      g_config.trace_file_size, g_config.force_stdin);
+      g_config.trace_file_size, g_config.force_stdin, focus_seg);
   if (g_config.symsan_env == NULL) {
     return SYMSAN_NO_MEMORY;
   }
diff --git a/include/launch.h b/include/launch.h
index 4249f22..7afd0c6 100644
--- a/include/launch.h
+++ b/include/launch.h
@@ -45,6 +45,10 @@ int symsan_set_trace_file_size(int enable);
 /// @brief set the force stdin mode for the target binary
 int symsan_set_force_stdin(int enable);
 
+/// @brief 选择性符号化:仅污染指定输入偏移(如 "0-3" 或 "0-3,8-11");
+///        NULL 或空串表示符号化全部字节(默认)。移植自 SymCC 的 SYMCC_FOCUS_BYTES。
+int symsan_set_focus_bytes(const char *spec);
+
 /// @brief run the target binary with the input file descriptor
 /// @param fd: input file descriptor, only used if input is "stdin"
 /// @return < 0 on syscall error, > 0 on setup error, 0 on success
diff --git a/runtime/dfsan/dfsan_custom.cpp b/runtime/dfsan/dfsan_custom.cpp
index 1ed98b5..7425e0b 100644
--- a/runtime/dfsan/dfsan_custom.cpp
+++ b/runtime/dfsan/dfsan_custom.cpp
@@ -229,12 +229,67 @@ static inline dfsan_label get_str_label(const char *s, dfsan_label s_label) {
   return get_str_label_n(s, s_label, len + 1, term_label);
 }
 
+// 选择性符号化(移植自 SymCC 的 initFocusBytes / _sym_get_input_byte):
+// 仅对 focus_bytes 指定的输入偏移打标签,其余偏移保持具体值(label 0 → 不污染)。
+// SymSan 的 taint 源是字节级的(每个输入偏移一个 label),因此在此单一枢纽处按偏移
+// 门控,即可让所有 read/pread/fread/mmap 等读入路径统一遵守选择集,缩小符号状态、
+// 减少无关字节的求解开销。区间语义与 SymCC 的 SYMCC_FOCUS_BYTES="s-e" 一致:
+// 区间内符号化、区间外具体化。
+#define DFSAN_MAX_FOCUS_RANGES 256
+struct FocusRange {
+  off_t lo;  // 闭区间下界
+  off_t hi;  // 闭区间上界
+};
+static FocusRange g_focus_ranges[DFSAN_MAX_FOCUS_RANGES];
+static int g_focus_count = -1;  // -1=未初始化; 0=无 focus(全字节符号化); >0=区间数
+
+// 解析 focus_bytes 规格串,如 "0-3" 或 "0-3,8-11" 或 "5"。不依赖 libc(strtol
+// 在 DFSan 运行时里被拦截可能不安全),手工按十进制逐位累加。
+static void init_focus_bytes() {
+  g_focus_count = 0;
+  const char *p = flags().focus_bytes;
+  if (!p || !p[0]) return;  // 未配置 → 保持默认(全字节符号化)
+  while (*p && g_focus_count < DFSAN_MAX_FOCUS_RANGES) {
+    while (*p == ',' || *p == ' ') ++p;  // 跳过分隔符
+    if (*p < '0' || *p > '9') { if (*p) ++p; continue; }
+    off_t lo = 0;
+    while (*p >= '0' && *p <= '9') { lo = lo * 10 + (*p - '0'); ++p; }
+    off_t hi = lo;
+    if (*p == '-') {
+      ++p;
+      hi = 0;
+      while (*p >= '0' && *p <= '9') { hi = hi * 10 + (*p - '0'); ++p; }
+    }
+    if (hi >= lo) {
+      g_focus_ranges[g_focus_count].lo = lo;
+      g_focus_ranges[g_focus_count].hi = hi;
+      ++g_focus_count;
+    }
+  }
+}
+
+// 该输入偏移是否应被符号化。无 focus 配置时恒为 true(默认行为不变)。
+static inline bool focus_active(off_t offset) {
+  if (g_focus_count < 0) init_focus_bytes();
+  if (g_focus_count == 0) return true;  // 无 focus → 所有字节符号化
+  for (int i = 0; i < g_focus_count; ++i)
+    if (offset >= g_focus_ranges[i].lo && offset <= g_focus_ranges[i].hi)
+      return true;
+  return false;
+}
+
 static inline dfsan_label get_label_for(int fd, off_t offset) {
   // check if fd is stdin, if so, the label hasn't been pre-allocated
-  if (is_stdin_taint() || (fd ==0 && flags().force_stdin))
-    return dfsan_create_label((uint64_t)fd, (uint64_t)(current_stdin_offset++), 1);
+  if (is_stdin_taint() || (fd ==0 && flags().force_stdin)) {
+    off_t off = current_stdin_offset++;  // 偏移必须始终自增以保持一致
+    if (!focus_active(off)) return 0;    // 选择性符号化:非 focus 字节保持具体
+    return dfsan_create_label((uint64_t)fd, (uint64_t)off, 1);
+  }
   // if fd is a tainted file, the label should have been pre-allocated
-  else return (offset + CONST_OFFSET);
+  else {
+    if (!focus_active(offset)) return 0;  // 选择性符号化:非 focus 字节保持具体
+    return (offset + CONST_OFFSET);
+  }
 }
 
 static void *dfsan_memcpy(void *dest, const void *src, size_t n) {
@@ -3938,8 +3993,11 @@ void __dfsw___libc_free(void *ptr, dfsan_label ptr_label) {
 
 static dfsan_label taint_getc(int fd, off_t offset, int ret) {
   if (ret != EOF && taint_get_file(fd)) {
-    dfsan_label label = label = dfsan_union(get_label_for(fd, offset), CONST_LABEL, ZExt, 32, 0, 0);
+    // BUG FIX: 原实现算出 label 却 `return 0`,导致每次 fgetc/getc 读入的字符都【丢污点】
+    // → getc 逐字符读入的程序(coreutils uniq/md5sum/who 等)的输入永不符号化。改为返回 label。
+    dfsan_label label = dfsan_union(get_label_for(fd, offset), CONST_LABEL, ZExt, 32, 0, 0);
     AOUT("%d label is readed by fgetc\n", label);
+    return label;
   }
   return 0;
 }
diff --git a/runtime/dfsan/dfsan_flags.inc b/runtime/dfsan/dfsan_flags.inc
index 046e3f3..cb4148f 100644
--- a/runtime/dfsan/dfsan_flags.inc
+++ b/runtime/dfsan/dfsan_flags.inc
@@ -54,3 +54,7 @@ DFSAN_FLAG(int, session_id, 0, "session/round id.")
 DFSAN_FLAG(bool, force_stdin, false, "force tainting stdin.")
 DFSAN_FLAG(bool, enum_gep, false, "enable GEP index enumeration.")
 DFSAN_FLAG(int, string_map_capacity, 256, "initial capacity for string label maps.")
+DFSAN_FLAG(const char *, focus_bytes, "",
+           "Selective symbolization: only taint these input byte offsets, e.g. "
+           "\"0-3\" or \"0-3,8-11\". Empty = taint all bytes (default). Ported "
+           "from SymCC SYMCC_FOCUS_BYTES.")
