(智能合约实习)LLVM 和 Rattle IR 的关系及 Rattle IR 的特点

111 阅读4分钟

LLVM 和 Rattle IR 的比较及 Rattle IR 的特点

什么是 LLVM?

LLVM 是一个用于构建编译器和工具链的开源框架,最初被设计为一种低级虚拟机 (Low Level Virtual Machine),但现已发展成一个通用的编译器基础设施。LLVM 支持从前端到后端生成机器代码的整个编译流程。它被广泛应用于编译器的开发,包括主流编程语言的编译器(如 Clang),以及一些需要代码优化和分析的工具。

什么是 Rattle IR?

Rattle 使用了一种专门为 EVM(以太坊虚拟机) 智能合约分析设计的自定义中间表示(IR)。Rattle 的 IR 以 SSA(静态单赋值)形式为基础,结合了适应 EVM 特性的特有指令和结构。这种 IR 能够从 EVM 字节码中提取并表示变量依赖、控制流和数据流,非常适用于智能合约的静态分析和逆向工程。

Rattle IR 的特点

  1. 基于 SSA 形式的单赋值规则

    • Rattle 的 IR 是基于 SSA(静态单赋值)的,确保每个变量在生成过程中只被赋值一次。
    • 通过 SSA 表示,Rattle 可以清晰地追踪变量来源,便于分析变量依赖关系。
  2. Phi 函数处理分支变量合并

    • Rattle 使用 phi 函数来合并控制流分支上的变量值。phi 函数在 SSA 表示中用于选择不同路径的变量值,从而满足 SSA 的单赋值约束。
  3. 自定义 EVM 特有指令

    • Rattle 的 IR 包含许多自定义的指令,如 PHIInstructionMethodDispatchInternalCallOp,这些指令并非原始 EVM 字节码的一部分,而是特意为静态分析设计的。
    • 例如,PHIInstruction 用于处理分支路径的变量值合并,MethodDispatch 表示条件函数调用(CONDICALL),而 InternalCallOp 表示内部分支调用。
    • 这些指令提供了更高层的抽象,简化了控制流和数据流的追踪流程,便于在不同路径上追踪变量值。
  4. 优化与指令简化

    • Rattle 会在 SSA 表示的基础上进行优化,删除堆栈操作指令如 DUPSWAPPUSHPOP,这些指令在 EVM 中用于管理堆栈,但在 SSA 表示中已不再需要。
    • 通过消除这些冗余的堆栈指令,Rattle 将字节码精简为原来的一半以上,使 SSA 表示更加简洁友好,从而简化了对智能合约逻辑的理解。
  5. 独立于 LLVM 的轻量级实现

    • 尽管 Rattle 的 IR 具有类似于 LLVM 的 SSA 特性和 phi 函数概念,但它完全是独立实现的,不依赖于 LLVM 的任何组件。
    • Rattle 的 IR 专为 EVM 字节码设计,去除了与智能合约分析无关的部分,使其更加轻量化和高效。

Rattle IR 的工作流程

Rattle 将 EVM 字节码转换为 SSA 表示,具体步骤如下:

  1. 输入字节码

    • Rattle 首先对 EVM 字节码进行分析,将其转换为寄存器式的 SSA 表示。通过 phi 函数处理分支中的变量合并,以确保变量只被赋值一次。
    • PlaceholderStackValue 用于表示控制流中尚不确定的变量,直到变量的值在后续代码中被确定。
  2. 消除冗余堆栈指令

    • 在 SSA 表示中,Rattle 优化地移除了 EVM 堆栈相关的 DUPSWAPPUSHPOP 等操作,将代码量减少 60% 以上。
  3. 变量依赖和控制流分析

    • Rattle 利用 SSA 表示中的 StackValueConcreteStackValue 跟踪变量状态,构建出完整的变量依赖和控制依赖路径。
    • 在 SSA 表示中,控制流中的分支条件通过 phi 函数处理,便于追踪和分析。
  4. 执行合约特性检测

    • 在 SSA 表示的基础上,Rattle 内置了如 can_send_ether 等函数,帮助检测智能合约的特定行为(如转账和调用),辅助检测潜在的合约漏洞和安全风险。

总结

Rattle 使用的自定义 IR 是一种专为 EVM 字节码的静态分析和逆向工程设计的轻量化中间表示。它的主要特点包括基于 SSA 的单赋值形式、自定义 EVM 特有指令、简化堆栈指令以及智能合约特性优化。这种 IR 独立于 LLVM,专为智能合约的分析需求量身打造,提升了代码分析的效率和简洁性。