强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

LLVM 开发指南 / 第 11 章:MC 层与汇编

第 11 章:MC 层与汇编

“MC 层是 LLVM 与硬件之间的最后一道桥梁。”


11.1 MC 层概述

MC(Machine Code)层是 LLVM 中最接近硬件的层次,负责:

  • MCInst 表示机器指令
  • 汇编器(Assembler):文本汇编 → 机器码
  • 反汇编器(Disassembler):机器码 → 文本汇编
  • 目标文件生成:ELF / MachO / COFF / WebAssembly
LLVM IR
  │
  ▼ (CodeGen)
MachineInstr
  │
  ▼ (AsmPrinter)
MCInst
  │
  ├──► MCAsmStreamer ──► 汇编文本 (.s)
  │
  └──► MCObjectStreamer ──► 目标文件 (.o)
         ├── ELF
         ├── MachO
         ├── COFF
         └── Wasm

11.2 MCInst

MCInst 是 MC 层的核心指令表示。

11.2.1 MCInst 结构

// MCInst 包含:
// 1. 操作码(Opcode)— 目标特定的操作码编号
// 2. 操作数列表(Operands)— 寄存器、立即数、内存引用等

// 示例:x86 的 "addl %ecx, %eax"
MCInst Inst;
Inst.setOpcode(X86::ADD32rr);
Inst.addOperand(MCOperand::createReg(X86::EAX));  // 目标寄存器
Inst.addOperand(MCOperand::createReg(X86::ECX));  // 源寄存器

// 示例:x86 的 "addl $42, %eax"
MCInst Inst;
Inst.setOpcode(X86::ADD32ri);
Inst.addOperand(MCOperand::createReg(X86::EAX));
Inst.addOperand(MCOperand::createImm(42));

11.2.2 MCOperand 类型

类型创建方法说明
寄存器MCOperand::createReg(Reg)物理寄存器编号
立即数MCOperand::createImm(Val)整数常量
浮点MCOperand::createFPImm(Val)浮点常量
表达式MCOperand::createExpr(Expr)符号表达式

11.3 MCStreamer

MCStreamer 是 MC 层的输出抽象:

11.3.1 两种输出流

// 1. 汇编输出 (MCAsmStreamer)
// 输出人类可读的汇编文本
// "addl %ecx, %eax\n"

// 2. 目标文件输出 (MCObjectStreamer)
// 输出二进制机器码
// → ELF / MachO / COFF
# 生成汇编
llc test.bc -o test.s

# 生成目标文件
llc -filetype=obj test.bc -o test.o

# 生成汇编(从 Clang)
clang -S test.c -o test.s

# 生成目标文件(从 Clang)
clang -c test.c -o test.o

11.4 MC 汇编解析器

11.4.1 使用 llvm-mc

# 汇编文本 → 目标文件
echo 'addl %ecx, %eax' | llvm-mc -triple=x86_64 --filetype=obj -o test.o

# 汇编文本 → 汇编(标准化)
echo 'addl %ecx, %eax' | llvm-mc -triple=x86_64 --show-encoding

# 反汇编
llvm-objdump -d test.o

# 使用 llvm-mc 作为汇编器
llvm-mc -triple=x86_64 test.s -filetype=obj -o test.o

11.4.2 使用 llvm-objdump

# 反汇编整个文件
llvm-objdump -d program

# 反汇编特定段
llvm-objdump -d -j .text program

# 显示源码与汇编对应
llvm-objdump -S program

# 显示符号表
llvm-objdump --syms program

# 显示重定位信息
llvm-objdump -r test.o

# 显示节头
llvm-objdump -h program

# 显示所有段的内容
llvm-objdump -s program

11.4.3 使用 llvm-nm

# 查看符号表
llvm-nm program

# 输出格式:
# 地址   类型  名称
# 004000  T    main
# 004010  T    add
#        U    printf  (未定义/外部符号)

11.5 目标文件格式

11.5.1 ELF(Linux)

# ELF 头信息
llvm-readelf -h program

# 节头表
llvm-readelf -S program

# 程序头表(段信息)
llvm-readelf -l program

# 重定位表
llvm-readelf -r test.o

# 动态符号
llvm-readelf --dyn-syms program

# DWARF 调试信息
llvm-readelf --debug-dump=info program

11.5.2 MachO(macOS)

# 使用 llvm-objdump 查看 MachO
llvm-objdump -h program.dylib
llvm-objdump --macho -d program

# 使用 llvm-readobj
llvm-readobj --macho-data program

11.5.3 COFF(Windows)

# 使用 llvm-readobj
llvm-readobj --coff-basereloc program.exe
llvm-readobj --coff-imports program.exe
llvm-readobj --coff-exports program.exe

11.6 llvm-mc 工具

# 汇编 → 目标文件
llvm-mc -triple=x86_64 test.s -filetype=obj -o test.o

# 汇编 → 标准汇编(规范化)
llvm-mc -triple=x86_64 test.s -show-encoding

# 查看指令编码
echo "nop" | llvm-mc -triple=x86_64 --show-encoding

# 显示指令信息
llvm-mc -triple=x86_64 -mattr=+avx2 --show-encoding <<< "vpaddb %ymm0, %ymm1, %ymm2"

11.7 链接器 (LLD)

LLD 是 LLVM 的高性能链接器,可替代 GNU ld。

# 使用 LLD 链接
clang -fuse-ld=lld test.o -o test

# 直接使用 LLD
ld.lld test.o -o test

# 生成共享库
ld.lld -shared test.o -o libtest.so

# 静态链接
ld.lld -static test.o -o test

# 查看链接过程
ld.lld --verbose test.o -o test 2>&1

# 生成 map 文件
ld.lld -Map=output.map test.o -o test

# 比较链接器速度
time ld.lld test.o -o test     # LLD (快)
time ld test.o -o test          # GNU ld (慢)

11.7.1 LLD 特性

特性说明
速度快比 GNU ld 快 2-10 倍
内存效率多线程并行
兼容性兼容 GNU ld 命令行
LTO 支持原生支持 LLVM LTO
调试信息高效处理 DWARF

11.8 本章小结

工具功能命令示例
llvm-mc汇编/反汇编llvm-mc -triple=x86_64 test.s -filetype=obj
llvm-objdump反汇编/查看llvm-objdump -d program
llvm-nm符号表llvm-nm program
llvm-readelfELF 分析llvm-readelf -h program
llvm-readobj通用目标文件分析llvm-readobj --all program
llvm-strip剥离符号llvm-strip program
llvm-objcopy目标文件操作llvm-objcopy --strip-debug
ld.lld链接器ld.lld test.o -o test

扩展阅读

  1. LLVM MC Documentation — MC 层文档
  2. ELF Spec — ELF 格式规范
  3. LLD Documentation — LLD 链接器文档

下一章: 第 12 章:LLVM 库与 API — 学习 libLLVM、libClang 和 LLVM C/C++ API。