reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
119
vendor-new/rev-skills/.claude/skills/re-swift/SKILL.md
Normal file
119
vendor-new/rev-skills/.claude/skills/re-swift/SKILL.md
Normal file
@@ -0,0 +1,119 @@
|
||||
---
|
||||
name: re-swift
|
||||
type: atomic
|
||||
description: >
|
||||
Swift 二进制逆向:mangling 解码、协议 witness table、闭包捕获、ObjC 互操作。
|
||||
触发词:Swift逆向、swiftc、witness table、swift demangle、闭包捕获、Swift 产物。
|
||||
capabilities: [lang-runtime-analysis]
|
||||
---
|
||||
|
||||
# Swift 逆向
|
||||
|
||||
## 何时使用 / 何时不用
|
||||
|
||||
- 用:Swift 产物(Mach-O/ELF 含 Swift mangling 特征 `$s` 前缀,或 `__swift5_*` 反射段),需要还原符号/协议一致性/闭包结构
|
||||
- 用:混合产物中区分 Swift 层与 ObjC/C 层(先走 ObjC 路径再进 Swift 层)
|
||||
- 不用:纯 ObjC(走 [[re-ios]] / [[re-macos]] 的 ObjC 路径);纯 C/C++(走 [[re-cpp-abi]])
|
||||
- 不用:只需普通反编译([[re-ghidra]] / [[re-ida]] 直接上)
|
||||
|
||||
## 工具准备
|
||||
|
||||
### swift-demangle(Swift 工具链,mangling 解码)
|
||||
|
||||
- macOS: Xcode 自带(`xcrun swift-demangle`);Linux: Swift 官方工具链(swift.org 下载 tar 包解压即用,含 `swift-demangle`);Windows: Swift 官方工具链
|
||||
- 验证: `echo '$s4main6myFuncyyF' | swift-demangle`(macOS 用 `xcrun swift-demangle`;无参数时读 stdin,输出 `$s... ---> main.myFunc() -> ()`)
|
||||
- 批量: `llvm-nm sample | swift-demangle`;`-simplified` 出精简名;`-expand` 出解码树
|
||||
|
||||
### swiftc / swift(可选,对照编译)
|
||||
|
||||
- macOS: Xcode 自带;Linux/Windows: 同上官方工具链(含编译器,可本地编译同版本样本对照符号形态)
|
||||
- 验证: `swift --version`
|
||||
|
||||
### llvm-nm / llvm-objdump(符号与段)
|
||||
|
||||
- 安装与验证见 [[re-cpp-abi]] 工具准备;Mach-O 侧额外需要 otool(见 [[re-format-macho]] 工具准备)
|
||||
- 用途: `llvm-nm -m sample` 看符号与段归属;`otool -l sample | grep swift5` 定位反射段
|
||||
|
||||
### Ghidra / IDA(反编译底座)
|
||||
|
||||
- 安装与验证见 [[re-ghidra]] / [[re-ida]];Swift 符号解码结果用于批量重命名(Ghidra 可脚本化:demangle 输出写回 symbol 表,反编译视图即恢复可读函数名)
|
||||
|
||||
## 操作步骤
|
||||
|
||||
按顺序执行,每步产物存档(路径 + sha256,见 [[re-triage]])。
|
||||
|
||||
1. **产物识别**:
|
||||
```sh
|
||||
strings -a sample | grep -E '^\$s|^_T0|^_\$S' | head
|
||||
llvm-nm sample 2>/dev/null | grep -E 'swift_|^\$s' | head # ELF 用 readelf -s 同效果
|
||||
otool -l sample 2>/dev/null | grep -c swift5 # Mach-O 反射段存在性
|
||||
```
|
||||
- `$s`(Swift 5+)、`$S`(Swift 4.2)、`_T0`(Swift 4.0)是三代 mangling 前缀;`swift_*` 运行时导入(swift_retain / swift_release / swift_allocObject)确认运行时
|
||||
- 纯 ObjC 无上述特征 → 转 [[re-ios]] / [[re-macos]];带 `__swift5_*` 段但 strip 了符号名 → 仍是 Swift(反射元数据不随 strip 消失,见坑 5)
|
||||
|
||||
2. **mangling 解码(批量)**:
|
||||
```sh
|
||||
llvm-nm -m sample | awk '$3 ~ /^\$s/ {print $3}' | swift-demangle | head -20
|
||||
# ELF: readelf -s sample | awk '$8 ~ /^\$s/ {print $8}' | swift-demangle
|
||||
```
|
||||
解码内容:模块名/类型/函数签名/泛型参数展开;结果写入符号表供 [[re-ghidra]] / [[re-ida]] 重命名。mangling 结构速览见步骤 3 与 [[layout]]。
|
||||
|
||||
3. **mangling 结构速览(手读符号)**:
|
||||
```
|
||||
$s 前缀 + 长度前缀标识符 + 类型字母 + 签名
|
||||
$s 13ExampleModule 3Foo C 3bar Si y F
|
||||
└模块(13字符) └类型 └类 └方法 └结果 └参数 └函数
|
||||
C=类 O=枚举 V=结构体 P=协议;Si=Int SS=String Sq=Optional;y=空元组 ()
|
||||
```
|
||||
编码规则:标识符=十进制长度+ASCII;签名顺序是**结果类型在前、参数在后**,`F` 结尾表示函数;签名可带修饰位(async/throws,解码输出中显式出现);`_To` 后缀=@objc 桥接 thunk;`TE` 后缀=distributed thunk。详细规则与官方示例见 [[layout]]/[[examples]]。
|
||||
|
||||
4. **协议 witness table(动态分派核心)**:
|
||||
- witness table 是协议方法的分发表;conformance 记录定位:Mach-O `__swift5_proto` 段 / ELF `swift5_protocol_conformances`(协议描述符在 `__swift5_protos` / `swift5_protocols`),或搜索 `_swift_getWitnessTable` 调用点
|
||||
- 还原:conformance 记录 = 方法槽位数组,槽值 = 对应协议要求的实现地址 → 结合 [[re-cpp-abi]] 的 vtable 恢复思路反推"哪个类型 conforms 哪个协议"
|
||||
- 无符号名时用协议方法调用点反推:找到 witness method 调用处的函数指针表,表序即协议声明序
|
||||
- 注意间接 conformance(`witness_table_indirect` 标志):槽位存的是间接表指针而非直接实现地址,需再解一层
|
||||
|
||||
5. **闭包捕获**:
|
||||
- 闭包是 context 对象:`swift_allocObject` 调用点 → context 分配 → 捕获字段初始化;context 头部是指向捕获布局描述符的指针,其后按捕获顺序排列字段
|
||||
- 还原:context 结构体字段 → 捕获变量名/类型(与函数签名关联);引用语义字段由 `swift_retain`/`swift_release` 调用点确认
|
||||
- 编译器生成的"partial apply forwarder"符号(解码含 `partial apply forwarder`)是闭包入点的典型形态
|
||||
|
||||
6. **ObjC 互操作**:
|
||||
- `@objc` 桥接:Swift 类经 ObjC runtime 可见(NSObject 子类、消息发送 objc_msgSend);Swift 侧实现入口是 `_To` 结尾的桥接 thunk
|
||||
- 分析:ObjC 方法列表(class-dump 思路)→ 桥接 thunk → Swift 实现;`swift_` 运行时函数调用点区分 Swift 侧逻辑
|
||||
- 混合产物:先走 ObjC 路径([[re-ios]] / [[re-macos]])再进 Swift 层;Linux 上的 Swift 产物无 ObjC 层(无 __objc_classlist),纯 ELF 视角分析
|
||||
|
||||
7. **反射元数据(类型结构还原)**:
|
||||
```sh
|
||||
otool -l sample | grep -A2 swift5_fieldmd # 字段描述(类型内布局)
|
||||
otool -l sample | grep -A2 swift5_typeref # 类型引用(字符串池)
|
||||
otool -l sample | grep -A2 swift5_reflstr # 反射字符串
|
||||
```
|
||||
`__swift5_fieldmd` 记录类型字段名/类型引用;配合 `__swift5_typeref` 可还原结构体/类布局,比纯反编译更快。
|
||||
|
||||
8. **符号化恢复**:解码结果批量重命名后,泛型特化符号(大量 `Gy` 后缀)按模块/类型聚类过滤,先恢复"每个类型的核心方法"再处理特化副本(见坑 2)。
|
||||
|
||||
9. **字节级核对**:符号提取/段定位输出异常时,用 `xxd` 按字节核对(mangled 名是长度前缀+ASCII,反射段是数据段内的定长记录)——最小字节样例与核对流程见 [[examples]],别把工具解析失败当"非 Swift 产物"丢弃。
|
||||
|
||||
## 跨域联合
|
||||
|
||||
- [[re-binary-core]] 网关:本技能归属(选择树「Swift 产物」分支)
|
||||
- [[re-ios]] / [[re-macos]]:生态衔接(ObjC 层、App 层分析)
|
||||
- [[re-format-macho]]:Mach-O 段/反射段定位工具链
|
||||
- [[re-cpp-abi]]:vtable/witness table 恢复思路同源
|
||||
- [[re-frida]]:运行时 hook Swift 函数(符号解码后的名称直接作 hook 点)
|
||||
- [[re-analyze/analysis-contract]]:符号表按数据契约传递
|
||||
|
||||
## 常见坑与陷阱
|
||||
|
||||
- **mangling 版本差异**:现象——新版本 Swift 产物解码失败或输出乱码;原因——mangling 方案演进(`$s`/`$S`/`_T0` 三代);对策——用与目标编译版本同代或更新的 swift-demangle,`_T0` 老符号新工具也能解,但新符号老工具不行
|
||||
- **泛型展开符号爆炸**:现象——解码输出大量 `$s...Gy` 泛型实例;原因——泛型特化;对策——按模块/类型聚类过滤,先还原未特化原型
|
||||
- **witness table 无符号名**:现象——分发表槽位全是裸地址;原因——协议 conformance 无命名符号;对策——结合协议方法调用点(witness method 调用处)反推槽位语义
|
||||
- **闭包捕获含引用语义**:现象——context 字段是引用计数对象;原因——捕获变量含类实例;对策——按 swift_retain/release 调用点确认引用字段,别当值类型读
|
||||
- **纯 ObjC 误入**:现象——无 `$s` 却按 Swift 流程走;原因——产物实为 ObjC;对策——步骤 1 先确认(无 `$s`/`__swift5_*` 即转)
|
||||
- **mangled 名不是普通字符串**:现象——`strings`/grep 截断或漏检部分符号;原因——mangled 名可含 `\x01-\x1f` 控制字符后跟指针字节(symbolic reference),不是以 `\0` 结尾的干净串;对策——符号提取用 `llvm-nm`/`readelf -s` 的符号表,不用 `strings` 兜底;解析器遇到控制字符要拒读指针字节
|
||||
- **strip 后反射段仍在但符号名没了**:现象——`__swift5_proto` 段还在、`$s` 符号列表为空;原因——strip 只删符号表,反射元数据(conformance/fieldmd)属数据段;对策——从反射段重建类型/协议关系,不依赖符号名
|
||||
- **`_To` 后缀被当普通符号**:现象——`foo.bar.bas(zim:)` 和 `@objc foo.bar.bas(zim:)` 两个符号并存,漏掉后者;原因——`_To` 是 @objc 桥接 thunk;对策——`_To` 与本体成对分析,ObjC 侧调用经 thunk 进 Swift 实现
|
||||
- **入口不是 ObjC 的 main 视角**:现象——按 `main` 函数分析发现"入口"只有薄薄一层;原因——Swift 可执行文件入口是 `@main`/顶层代码经运行时初始化(swift_retain 大量出现于启动路径);对策——从 `main` 反汇编沿运行时调用链找到第一个用户类型的方法调用点再深入,别在初始化包装里打转
|
||||
- **Swift 4 老产物无反射段**:现象——没有 `__swift5_*` 段、符号又被 strip,只剩 `_T`/`_T0` 前缀残迹;原因——反射系统 5.0 才引入;对策——按 mangling 前缀(`_TtC` 等)与 `swift_retain`/`swift_release` 运行时调用点识别 Swift 侧代码,从 ObjC 段(__objc_classlist)补类型骨架
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
# Swift 最小解析示例
|
||||
|
||||
示例符号均取自官方测试向量(swiftlang/swift test/Demangle/Inputs/manglings.txt 与 ABI 文档 Mangling.rst),可本机直接对照。语法规则见 [[layout]]。
|
||||
|
||||
## 1. 符号提取与解码命令链
|
||||
|
||||
```sh
|
||||
# Mach-O: 提取 $s 符号 → 批量解码
|
||||
llvm-nm -m sample | awk '$3 ~ /^\$s/ {print $3}' | swift-demangle | head -20
|
||||
# ELF 同效果
|
||||
readelf -s sample | awk '$8 ~ /^\$s/ {print $8}' | swift-demangle | head -20
|
||||
# 单条解码(macOS 用 xcrun swift-demangle;无参数时读 stdin)
|
||||
echo '$s4main6myFuncyyF' | swift-demangle
|
||||
# $s4main6myFuncyyF ---> main.myFunc() -> ()
|
||||
# 精简模式与展开树
|
||||
echo '$s4main3FooC3barSiyF' | swift-demangle -simplified
|
||||
echo '$s4main3FooC3barSiyF' | swift-demangle -expand
|
||||
```
|
||||
|
||||
## 2. 官方测试向量对照(manglings.txt 实测摘录)
|
||||
|
||||
| mangled 名 | demangled 结果 |
|
||||
|---|---|
|
||||
| `$s4main6myFuncyyF` | `main.myFunc() -> ()` |
|
||||
| `$s3foo3barC3bas3zimyAaEC_tF` | `foo.bar.bas(zim: foo.zim) -> ()` |
|
||||
| `_$s3foo3barC3bas3zimyAaEC_tFTo` | `{T:_$s3foo3barC3bas3zimyAaEC_tF,C} @objc foo.bar.bas(zim: foo.zim) -> ()`(`_To` = @objc 桥接 thunk) |
|
||||
| `$s4main3fooyySiFyyXEfU_TA.1` | `{T:} partial apply forwarder for closure #1 () -> () in main.foo(Swift.Int) -> () with unmangled suffix ".1"`(闭包 forwarder) |
|
||||
| `$s4main8MyStructV3fooyyF` | `main.MyStruct.foo() -> ()`(结构体方法) |
|
||||
| `_T04main1_yyF` | `main._() -> ()`(Swift 4.0 `_T0` 前缀) |
|
||||
| `_TtVCC4main3Foo4Ding3Str` | `main.Foo.Ding.Str`(Swift 3.x `_Tt` 前缀,V=struct 链) |
|
||||
|
||||
对照要点:`yyF` 中两个 `y` 分别是结果 `()` 与参数 `()`;`Si` 为结果 Int 时排在参数前(`3barSiyF` → `bar() -> Int`);`_To` 与本体成对出现;`TA` 是闭包 forwarder(闭包入点)。
|
||||
|
||||
## 3. Python 最小解码器(无替换/无泛型的简单符号)
|
||||
|
||||
```python
|
||||
import re
|
||||
KIND = {'C': 'class', 'O': 'enum', 'V': 'struct', 'P': 'protocol'}
|
||||
STDLIB = {'Si': 'Int', 'SS': 'String', 'Sq': 'Optional', 'Sa': 'Array',
|
||||
'Sd': 'Double', 'Sb': 'Bool'}
|
||||
|
||||
def ident(sym, p): # 长度前缀标识符:3Foo -> "Foo"
|
||||
m = re.match(r'(\d+)', sym[p:])
|
||||
n = int(m.group(1)); start = p + len(m.group(1))
|
||||
return sym[start:start+n], start+n
|
||||
|
||||
def typ(sym, p): # 类型单元:y=() Si=Int ...
|
||||
c = sym[p]
|
||||
if c == 'y': return '()', p + 1
|
||||
if c == 'S': return STDLIB.get(sym[p:p+2], 'S?'), p + 2
|
||||
raise ValueError('unhandled type char %r' % c)
|
||||
|
||||
def sig(sym, p): # 签名顺序:结果类型在前、参数在后
|
||||
result, p = typ(sym, p)
|
||||
params, p = typ(sym, p)
|
||||
if sym[p] != 'F': raise ValueError('no F')
|
||||
return '%s -> %s' % (params, result), p + 1
|
||||
|
||||
def decode(sym):
|
||||
p = 2 if sym.startswith('$s') else 3 # 仅支持 $s / _$s
|
||||
mod, p = ident(sym, p)
|
||||
parts = [mod]
|
||||
while p < len(sym) and sym[p].isdigit():
|
||||
name, p = ident(sym, p)
|
||||
if p < len(sym) and sym[p] in KIND:
|
||||
parts.append('%s (%s)' % (name, KIND[sym[p]])); p += 1
|
||||
else:
|
||||
parts.append(name)
|
||||
s, _ = sig(sym, p)
|
||||
return '.'.join(parts) + s
|
||||
|
||||
print(decode('$s4main6myFuncyyF')) # main.myFunc() -> ()
|
||||
print(decode('$s4main3FooC3barSiyF')) # main.Foo (class).bar() -> Int
|
||||
print(decode('$s13ExampleModule3FooC3barSiyF')) # ExampleModule.Foo (class).bar() -> Int
|
||||
```
|
||||
|
||||
局限(对照官方语法):不处理替换表(`A` 起)、泛型签名(`G`)、标签列表、`E` 扩展与 `To/TE/Tg` 后缀——复杂符号以 `swift-demangle` 为准,本解码器用于快速手读与理解编码顺序。
|
||||
|
||||
## 4. 反射段定位(stripped 产物的类型结构来源)
|
||||
|
||||
```sh
|
||||
otool -l sample | grep -A2 'sectname __swift5_proto' # conformance 记录
|
||||
otool -l sample | grep -A2 'sectname __swift5_protos' # 协议描述符
|
||||
otool -l sample | grep -A2 'sectname __swift5_fieldmd' # 字段描述
|
||||
otool -l sample | grep -A2 'sectname __swift5_types' # 类型描述符
|
||||
# ELF 侧
|
||||
readelf -S sample | grep -i swift5
|
||||
```
|
||||
|
||||
## 5. 字节样例(符号在文件中的形态)
|
||||
|
||||
```
|
||||
$s4main6myFuncyyF 的 ASCII 字节(符号表字符串池内):
|
||||
24 73 34 6d 61 69 6e 36 6d 79 46 75 6e 63 79 79 46 00
|
||||
$ s 4 m a i n 6 m y F u n c y y F \0
|
||||
└前缀┘ └模块"main"┘ └函数名"myFunc"┘ └yyF 签名┘
|
||||
```
|
||||
|
||||
对照要点:正常符号以 `\0` 结尾(字符串表内),但含 symbolic reference 的符号名内嵌 `\x01-\x1f` + 指针字节,`strings`/`grep` 按文本处理会截断——提取一律走符号表(llvm-nm/readelf -s)。
|
||||
|
||||
## 实现教训(内化)
|
||||
|
||||
- 解码顺序是"模块 → 类型上下文 → 实体名 → 签名",签名里结果类型在参数前——手读符号按这个顺序切,别倒着猜
|
||||
- `_To`/`TA`/`Tg5` 等后缀是实体修饰,解码时先剥离再读主体
|
||||
- 官方测试向量(manglings.txt)是最好的离线对照集:任何解码器/工具的输出都可拿它验收
|
||||
|
||||
## 使用注意
|
||||
|
||||
- 符号提取用符号表工具,不用 strings;strip 产物靠 `__swift5_*` 反射段(见 SKILL.md 坑 5)
|
||||
- 与 [[re-format-macho]](段定位)、[[re-cpp-abi]](vtable 思路)配合使用
|
||||
@@ -0,0 +1,118 @@
|
||||
# Swift 二进制布局:mangling 语法 / swift5 反射段 / witness table / 闭包
|
||||
|
||||
Swift 产物相对 C/C++ 产物多两类结构:mangled 符号名(全部顶层符号经 `$s` 编码)与 `__swift5_*` 反射元数据段(协议一致性、类型描述、字段描述)。两者互补:符号名给"名字",反射段给"结构"。
|
||||
|
||||
## mangling 前缀变体
|
||||
|
||||
| 前缀 | 时期 | 说明 |
|
||||
|---|---|---|
|
||||
| `$s` | Swift 5+ | 当前稳定 mangling(本技能默认处理对象) |
|
||||
| `$S` | Swift 4.2 | 4.2 过渡期变体 |
|
||||
| `_T0` | Swift 4.0 | 4.0 变体 |
|
||||
| `_T` / `_Tt` | Swift 3.x 及更早 | ObjC 时代 mangling(`_TtC3foo3bar` 形态) |
|
||||
| `$e` | — | Embedded Swift(不稳定) |
|
||||
| `@__swiftmacro_` | — | 宏展开的文件名符号 |
|
||||
|
||||
## 编码语法(`$s` 稳定格式)
|
||||
|
||||
### 基本单元
|
||||
|
||||
| 单元 | 规则 | 示例 |
|
||||
|---|---|---|
|
||||
| 标识符 | 十进制长度 + ASCII 字符串(非 ASCII 用 Punycode,前缀 `00`) | `4Test` → "Test";`13ExampleModule` → "ExampleModule" |
|
||||
| 类型字母 | C=类 O=枚举 V=结构体 P=协议 E=扩展 | `3FooC` → 类 Foo |
|
||||
| 标准库缩写 | Si=Int SS=String Sq=Optional Sa=Array Sd=Double Sb=Bool | `Si` → Swift.Int |
|
||||
| 模块缩写 | s=Swift So=C/ObjC 模块 SC=Clang importer | `s4main` 中 `s` 为 Swift 模块 |
|
||||
| 空元组 | y | `() `(参数或结果为空) |
|
||||
| 函数 | 声明名 + 标签列表 + 签名 + `F`;**签名顺序 = 结果类型在前、参数在后** | `3bar Si y F` → `bar() -> Int` |
|
||||
|
||||
### 后缀修饰(实体级)
|
||||
|
||||
| 后缀 | 含义 |
|
||||
|---|---|
|
||||
| `_To` | @objc 桥接 thunk(与本体成对出现,ObjC 侧经它进 Swift 实现) |
|
||||
| `TE` | distributed thunk |
|
||||
| `Tg5`/`Tg` 等 | 泛型特化(generic specialization) |
|
||||
| `TA` | 闭包 partial apply forwarder |
|
||||
| `TW` | 协议 witness thunk(`{T:} protocol witness for ...`) |
|
||||
| `TI` | 可派发 thunk(method dispatch thunk) |
|
||||
|
||||
### 替换与符号化引用
|
||||
|
||||
- 替换表(substitution):`A` 起的小写字母引用已出现的模块/类型(压缩重复前缀)
|
||||
- 符号化引用(symbolic reference):mangled 名内嵌 `\x01-\x1f` 控制字符 + 指针大小字节——**不是 \0 结尾的普通字符串**,`strings`/strlen 处理会截断(见 SKILL.md 坑 6)
|
||||
|
||||
### 手读示例(官方测试向量)
|
||||
|
||||
```
|
||||
$s4main6myFuncyyF → main.myFunc() -> ()
|
||||
└模块"main"└函数"myFunc"└结果y(())└参数y(())└F
|
||||
|
||||
$s3foo3barC3bas3zimyAaEC_tF → foo.bar.bas(zim: foo.zim) -> ()
|
||||
└模块foo └类bar └方法bas └标签zim └参数y └结果(替换A→foo.zim)└F
|
||||
|
||||
$s3foo3barC3bas3zimyAaEC_tFTo → {T:...,C} @objc foo.bar.bas(zim: foo.zim) -> ()
|
||||
(同符号 + _To = @objc 桥接 thunk)
|
||||
|
||||
$s4main3fooyySiFyyXEfU_TA.1 → {T:} partial apply forwarder for closure #1
|
||||
() -> () in main.foo(Swift.Int) -> ()(闭包)
|
||||
```
|
||||
|
||||
## swift5 反射段(Mach-O 名 / ELF 名 / COFF 名)
|
||||
|
||||
| 内容 | Mach-O(__TEXT 段内) | ELF | COFF |
|
||||
|---|---|---|---|
|
||||
| 协议一致性(conformance 记录) | `__swift5_proto` | `swift5_protocol_conformances` | `.sw5prtc$B` |
|
||||
| 协议描述符 | `__swift5_protos` | `swift5_protocols` | `.sw5prt$B` |
|
||||
| 类型描述符 | `__swift5_types` | `swift5_types` | `.sw5tyd$B` |
|
||||
| 字段描述(类型内布局) | `__swift5_fieldmd` | `swift5_fieldmd` | `.sw5fld$B` |
|
||||
| 类型引用字符串池 | `__swift5_typeref` | `swift5_typeref` | `.sw5tyr$B` |
|
||||
| 反射字符串 | `__swift5_reflstr` | `swift5_reflstr` | `.sw5rfl$B` |
|
||||
| 闭包捕获描述 | `__swift5_capture` | `swift5_capture` | `.sw5cpt$B` |
|
||||
| 关联类型 | `__swift5_assocty` | `swift5_assocty` | `.sw5ast$B` |
|
||||
| 内建类型 | `__swift5_builtin` | `swift5_builtin` | `.sw5bui$B` |
|
||||
| 多态枚举 | `__swift5_mpenum` | `swift5_mpenum` | `.sw5mpe$B` |
|
||||
| 可访问性 | `__swift5_accessible` | `swift5_accessible` | `.sw5acc$B` |
|
||||
| 替换范围 | `__swift5_replace` | `swift5_replace` | `.sw5rpc$B` |
|
||||
| 模块哈希 | `__swift_modhash` | `swift_modhash` | `.sw5mh$B` |
|
||||
|
||||
定位命令:Mach-O `otool -l sample | grep -A2 swift5_`;ELF `readelf -S sample | grep -i swift5`。这些段是数据段(常驻内存),**strip 不删除**——stripped Swift 产物靠它们重建类型/协议关系。
|
||||
|
||||
## witness table 与 conformance 记录
|
||||
|
||||
- conformance 记录(`__swift5_proto`)指向:witness table(若间接)、conformance 描述符、名义类型描述符、协议描述符
|
||||
- witness table 槽位 = 协议要求方法的实现地址数组;槽序与协议声明顺序一致
|
||||
- 定位入口:`_swift_getWitnessTable`(直接取)或 `swift_getWitnessTable`(查表)调用点;调用处的第二个参数即 conformance 记录
|
||||
- 无符号名时:找到 witness method 调用点(泛型函数内对协议方法的间接调用),其函数指针表即 witness table
|
||||
|
||||
## 闭包 context 布局
|
||||
|
||||
```
|
||||
swift_allocObject(闭包布局描述符, size, align) → context 对象
|
||||
context 头部 = 指向闭包捕获布局描述符的指针(swift5_capture 段条目)
|
||||
其后按捕获顺序排列字段:值类型=内联值;引用类型=强引用指针(配 swift_retain/release)
|
||||
```
|
||||
|
||||
定位:`swift_allocObject` 调用点的常量参数 = 捕获布局描述符(含捕获字段数/类型);闭包入点是 partial apply forwarder(`TA` 后缀符号)。
|
||||
|
||||
## 运行时符号(swift_ 前缀,导入确认)
|
||||
|
||||
| 符号 | 含义 |
|
||||
|---|---|
|
||||
| swift_retain / swift_release | 强引用增/减(引用语义字段标记) |
|
||||
| swift_allocObject / swift_allocBox | 堆对象/闭包 box 分配 |
|
||||
| swift_beginAccess / swift_endAccess | 独占访问修饰(exclusivity) |
|
||||
| swift_getWitnessTable / _swift_getWitnessTable | 协议 witness table 获取 |
|
||||
| swift_getTypeByMangledName | 按 mangled 名查类型元数据 |
|
||||
| swift_dynamicCast | 动态类型转换 |
|
||||
|
||||
## 版本差异要点
|
||||
|
||||
- mangling 前缀三代($s/$S/_T0),工具链与产物同代或更新才能解码
|
||||
- Swift 4 及更早产物无 `__swift5_*` 段(反射系统 5.0 引入);老产物靠符号名 + ObjC 段(__objc_classlist)恢复
|
||||
- 泛型特化数量随版本增长(编译器更激进);`Tg5` 特化符号与原型共存
|
||||
|
||||
## 使用注意
|
||||
|
||||
- 与 [[re-format-macho]](段定位)、[[re-cpp-abi]](vtable 思路)、[[re-ios]]/[[re-macos]](ObjC 层)配合
|
||||
- 符号提取走符号表(llvm-nm/readelf -s),不用 strings(symbolic reference 会截断)
|
||||
Reference in New Issue
Block a user