通过 Ghidra 进行 RISC-V ELF 分析¶
此通道扩展了对 EM_RISCV 目标的原生 ELF 分析。它不会执行 RISC-V 代码、模拟启动序列或重新托管固件。它解决 #2063 问题,并遵循与 通用 MIPS 支持 相同的通道形态。
准入边界¶
ELF EM_RISCV (243) 被保留为不限定提供方的 riscv 族。该目标同样保留决定通道的原始 ELF 声明:类别、字节序、e_type 和 e_flags。被识别并不意味着所有提供方或 RISC-V 变体都受支持。现有的 PE、托管和 Mach-O 架构集保持不变。无头输入使用独立的 原始二进制准入边界;不支持原始 RISC-V 镜像。
Ghidra 通道接纳在 e_flags 中声明 EF_RISCV_FLOAT_ABI_DOUBLE 的小端 ELF32 和 ELF64 ET_EXEC 镜像,并且不得包含 EF_RISCV_RVE、EF_RISCV_TSO,或 EF_RISCV_RVC | EF_RISCV_FLOAT_ABI 之外的任何位。这些是头部声明,并不证明每条指令都符合该 ISA。
提供方选择会返回具体的、不受支持的约束条件,而不是猜测一个兼容的配置文件:
| 声明 | 结果 |
|---|---|
小端 ELF64 ET_EXEC,双精度浮点 ABI |
准入,RISCV:LE:64:default + gcc |
小端 ELF32 ET_EXEC,双精度浮点 ABI |
准入,RISCV:LE:32:default + gcc |
| 大端 | 拒绝;Ghidra 12.1.4 未随附大端 RISC-V 语言 |
ET_REL、ET_DYN 或其他 e_type |
拒绝,并附上声明的值 |
EF_RISCV_RVE |
拒绝;嵌入式 16 寄存器配置文件(x0–x15)需要自己的处理器规范 |
EF_RISCV_TSO |
拒绝;总存储序内存模型在此未经验证 |
| 软浮点、单精度或四精度浮点 ABI | 拒绝;固定的通用编译器规范对双精度浮点建模 |
保留或更新的 e_flags 位 |
拒绝,并指出违规位 |
e_type 是此通道读取的唯一加载形态声明。固定地址的 ET_EXEC 声明并不建立静态链接:不检查 PT_INTERP 和动态依赖,会话会将此边界记录为限制,而不是推断加载模型。
为什么语言被固定¶
Ghidra 基于头的选择对 RV32 不可靠。12.1.4 的 riscv.opinion 为 64 位约束固定了 variant="default",并让 32 位约束保持不固定,注释称加载器“必须在 'default' 和 'AndeStar' 变体之间选择”。对照已安装的发布树测量:
| 夹具 | Ghidra 自动选择 |
|---|---|
RV64 ELF,e_flags 0x5(RVC,双精度浮点 ABI) |
RISCV:LE:64:default:gcc |
RV32 ELF,e_flags 0x5,无 Andes 声明 |
RISCV:LE:32:AndeStar_v5:gcc |
因此,除非明确指定语言,否则普通的 RV32 镜像会落到 Andes 处理器模型上。因此 REA 按类别固定 RISCV:LE:32:default 或 RISCV:LE:64:default 以及 gcc 编译器规范,记录 language_selection: provider-pinned-v1,并拒绝调用者选择的、与固定不一致的 REA_GHIDRA_LANGUAGE_ID 或 REA_GHIDRA_COMPILER_SPEC_ID,同时不改变请求的覆盖项。与固定匹配的覆盖项会被接受并记录为 configured-v1。
证据¶
通道身份为 elf32-exec-le-double-float-generic-v1 或 elf64-exec-le-double-float-generic-v1,并且 riscv_elf 保留 elf_class、byte_order、type 和原始 flags,以及只读布尔值 float_abi_double、rvc_declared、rve_declared 和 tso_declared。这些字段报告头部所做的声明;它们都不能证明原始编译器、指令符合性,或除固定语言所建模的 ABI 之外的任何浮点调用约定。
验证与限制¶
需要 Ghidra 12.1.4 PUBLIC 和 64 位 JDK 21+;并且在 macOS 上,发布树不随附主机反编译器二进制文件,因此 Decompiler/os/<platform>/decompile 和 sleigh 必须来自你自己的构建;参见 安装。
使用现有的 Ghidra 12.1.4 安装、JDK 21+ 以及支持 RISC-V 的 Clang、LLD 和 LLVM readelf 运行 npm run verify:ghidra:riscv。验证器不获取任何工具,也从不执行目标代码。当已安装的工具不在 PATH 中时,请显式选择它们:
GHIDRA_INSTALL_DIR=/path/to/ghidra_12.1.4_PUBLIC \
JAVA_HOME=/path/to/jdk-21 \
REA_RISCV_CLANG=/path/to/llvm/bin/clang \
REA_RISCV_LLD=/path/to/lld/bin/ld.lld \
REA_RISCV_READELF=/path/to/llvm/bin/llvm-readelf \
npm run verify:ghidra:riscv
该通道将已提交的独立式(freestanding)C 和汇编源码构建为 RV32 和 RV64 ET_EXEC 夹具。独立的 LLVM readelf 观察结果确立 ELF 声明和符号地址。公共 CLI 和 stdio MCP 工作流验证函数枚举、反编译、固定的语言/编译器身份、解码后的探测字节、全局数据和直接调用。它还会验证所声明的 MCP 输出模式及两种 JSON 表示,保存并重新打开快照,拒绝头部被篡改的软浮点声明和不受支持的高位声明,并检查未更改的源字节和所拥有的清理过程。失败时保留诊断工作区;成功运行则将其移除并报告观察到的进程谱系。
模块测试涵盖准入检查和畸形头部。调用图完整性、字符串清单、动态链接、Andes 或 RVE/TSO 镜像以及 big-endian 目标均不由该测试通道验证。.riscv.attributes ISA 扩展未受检查;通用语言固定仍是一种分析约定。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 rea2/rea