本文深入概述了 Ghidra 对 x86 处理器架构系列的支持。它涵盖了寄存器集、寻址模式、指令变体以及各种 x86 指令集扩展(包括 AVX、AVX2 和 AVX-512)的实现。有关 ARM 架构支持的信息,请参阅ARM 架构支持。
Ghidra 为整个 x86 架构系列提供全面支持,包括 16 位、32 位和 64 位变体。这些处理器变体在语言定义文件中定义。
来源:Ghidra/Processors/x86/data/languages/x86.ldefs4-120
每个变体都定义了特定的处理器规格和编译器支持。下表显示了每个变体可用的编译器支持
| 处理器变体 | 支持的编译器 |
|---|---|
| 32 位 x86 | Visual Studio, Clang, GCC, Borland C++, Delphi, Go |
| 16 位真实模式 | 默认编译器规范 |
| 16 位保护模式 | 默认编译器规范 |
| 64 位 x86 | Visual Studio, Clang, GCC, Go, Swift |
| 64 位 (compat32) | Visual Studio, GCC |
来源:Ghidra/Processors/x86/data/languages/x86.ldefs14-119
x86 架构包含多种寄存器,它们在不同的处理器世代中演变。Ghidra 建模了所有这些寄存器,并提供了精确的位级别规范,以支持对所有变体进行适当的分析。
来源:Ghidra/Processors/x86/data/languages/ia.sinc17-37
x86 架构包含段寄存器和专用寄存器
来源:Ghidra/Processors/x86/data/languages/ia.sinc35-36 Ghidra/Processors/x86/data/languages/ia.sinc38-49 Ghidra/Processors/x86/data/languages/ia.sinc506-521
Ghidra 支持各种 x86 扩展的所有 SIMD 寄存器集
来源:Ghidra/Processors/x86/data/languages/ia.sinc92-127 Ghidra/Processors/x86/data/languages/ia.sinc155-364 Ghidra/Processors/x86/data/languages/ia.sinc371-373
Ghidra 的 x86 实现利用 Sleigh 语言定义处理器的指令集。该实现是模块化的,并组织成独立的文件,用于不同的指令集扩展。
来源:Ghidra/Processors/x86/data/languages/x86.slaspec1-21 Ghidra/Processors/x86/data/languages/x86-64.slaspec1-7
Ghidra 的 x86 实现采用全面的基于令牌的方法来解码复杂的指令集,该指令集具有可变长度编码和多个前缀。指令解码过程处理:
来源:Ghidra/Processors/x86/data/languages/ia.sinc397-469 Ghidra/Processors/x86/data/languages/ia.sinc523-661
指令语义使用 Ghidra 的中间表示 P-code 实现。为复杂的 x86 行为定义了特殊的 P-code 操作:
| P-code 操作 | 目的 |
|---|---|
segment | 根据段和偏移计算 RAM 地址 |
in/out | I/O 端口操作 |
sysenter/sysexit | 系统调用操作 |
syscall/sysret | 64 位系统调用操作 |
LOCK/UNLOCK | 用于原子操作的内存锁定 |
XACQUIRE/XRELEASE | 事务性内存操作 |
来源:Ghidra/Processors/x86/data/languages/ia.sinc725-748
64 位扩展增加了:
来源:Ghidra/Processors/x86/data/languages/x86-64.slaspec1-7
Ghidra 实现了多代 SIMD 扩展:
实现细节因扩展而异
AVX 指令使用 VEX 前缀编码并引入 256 位操作
来源:Ghidra/Processors/x86/data/languages/avx.sinc6-94 Ghidra/Processors/x86/data/languages/avx_manual.sinc1-33
AVX-512 通过 EVEX 前缀扩展了 AVX,提供了对 512 位操作的支持,并增加了掩码功能
来源:Ghidra/Processors/x86/data/languages/avx512.sinc6-131 Ghidra/Processors/x86/data/languages/avx512_manual.sinc2-56
Ghidra 支持许多其他 x86 扩展:
| 扩展 | 描述 | 实现文件 |
|---|---|---|
| BMI1 | 位操作指令 1 | bmi1.sinc |
| BMI2 | 位操作指令 2 | bmi2.sinc |
| FMA | 乘加融合 | fma.sinc |
| PCLMULQDQ | 无进位乘法 | pclmulqdq.sinc |
| LZCNT | 前导零计数 | lzcnt.sinc |
| RDRAND | 硬件随机数生成器 | rdrand.sinc |
| ADX | 多精度带进位加法 | adx.sinc |
| MPX | 内存保护扩展 | mpx.sinc |
| SGX | 软件防护扩展 | sgx.sinc |
| SMX | 更安全模式扩展 | smx.sinc |
来源:Ghidra/Processors/x86/data/languages/x86.slaspec10-20 Ghidra/Processors/x86/certification.manifest9-76
Ghidra 实现了各种 x86 寻址模式,包括用于 16 位模式的段:偏移寻址和用于 32/64 位模式的复杂 ModR/M 和 SIB 字节组合。
来源:Ghidra/Processors/x86/data/languages/ia.sinc628-645
Ghidra 的 x86 实现处理 x86 指令复杂的上下文相关特性,包括:
上下文寄存器存储影响指令解码的各种状态位
| 上下文位 | 目的 |
|---|---|
| longMode | 64 位模式指示符 |
| addrsize | 16/32/64 位寻址模式 |
| opsize | 16/32/64 位操作数大小 |
| segover | 段覆盖 |
| protectedMode | 保护模式指示符 |
| vexMode | VEX 指令模式 |
| evexL | EVEX 向量长度 |
| evexZ | EVEX 归零/合并 |
| evexB | EVEX 广播/舍入 |
| evexAAA | EVEX 掩码寄存器 |
来源:Ghidra/Processors/x86/data/languages/ia.sinc367-470
Ghidra 通过 LOCK 前缀支持 x86 原子操作,该前缀作为特例实现。lockable.sinc 文件定义了可以带 LOCK 前缀的指令。
可锁定指令包括:
来源:Ghidra/Processors/x86/data/languages/lockable.sinc1-6 Ghidra/Processors/x86/data/languages/lockable.sinc7-952
x86 处理器模块由多个语言定义文件定义,这些文件指定 Ghidra 支持的处理器变体:
| 处理器变体 | ID | 描述 |
|---|---|---|
| x86:LE:32:default | 32 位 Intel/AMD x86 | 标准 32 位 x86 |
| x86:LE:32:System Management Mode | 系统管理模式 | SMM 中的 32 位 x86 |
| x86:LE:16:Real Mode | 16 位真实模式 | 真实模式下的 x86 |
| x86:LE:16:Protected Mode | 16 位保护模式 | 16 位保护模式下的 x86 |
| x86:LE:64:default | 64 位 Intel/AMD x86 | 标准 64 位 x86-64 |
| x86:LE:64:compat32 | 64 位 compat32 | 具有 32 位兼容性的 64 位模式 |
每个处理器变体都有相关的编译器规范,用于正确处理函数原型和调用约定。