reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
114
vendor-new/rev-skills/.claude/skills/re-nim/SKILL.md
Normal file
114
vendor-new/rev-skills/.claude/skills/re-nim/SKILL.md
Normal file
@@ -0,0 +1,114 @@
|
||||
---
|
||||
name: re-nim
|
||||
type: atomic
|
||||
description: >
|
||||
Nim 编译产物逆向:运行时识别、NimString 结构、异常与 GC 路径。
|
||||
触发词:Nim逆向、nim、NimString、NimMain、nim 产物。
|
||||
capabilities: [lang-runtime-analysis]
|
||||
---
|
||||
|
||||
# Nim 逆向
|
||||
|
||||
## 何时使用 / 何时不用
|
||||
|
||||
- 用:Nim 产物(`NimMain` / GC 符号、NimString 结构特征),需要还原字符串逻辑、异常路径、GC/所有权关系
|
||||
- 用:Nim/C 混合产物中区分 Nim 侧代码(按符号来源分组后 Nim 侧进本技能路径)
|
||||
- 不用:纯 C/C++ 产物(走 [[re-cpp-abi]] / [[re-binary-core]] 通用路径)
|
||||
- 不用:只需函数逻辑(直接反编译技能)
|
||||
|
||||
## 工具准备
|
||||
|
||||
### readelf / llvm-nm(符号与节分析)
|
||||
|
||||
- 安装与验证见 [[re-cpp-abi]] 工具准备
|
||||
- Nim 产物以 ELF 为主(Linux 默认 C 后端);macOS 用 llvm-nm
|
||||
|
||||
### Ghidra / IDA(反编译底座)
|
||||
|
||||
- 安装与验证见 [[re-ghidra]] / [[re-ida]];Nim 符号(NimMain/NimStringV2 等)导入后直接可读
|
||||
|
||||
### nim 编译器(可选,对照编译)
|
||||
|
||||
- Linux: `apt install nim` / `dnf install nim` / `pacman -S nim`;macOS: `brew install nim`;Windows: choosenim/官方安装器
|
||||
- 验证: `nim -v`;用途: 同版本编译对照产物,验证字符串布局/GC 符号形态(版本差异见 [[layout]])
|
||||
|
||||
### xxd + Python struct(字节级核对)
|
||||
|
||||
- 系统自带(`xxd`);Python 3 自带 `struct`
|
||||
- 用途: 符号/布局输出异常时按偏移直接解析 NimString 与对象结构(示例见 [[examples]])
|
||||
|
||||
## 操作步骤
|
||||
|
||||
按顺序执行,每步产物存档(路径 + sha256,见 [[re-triage]])。
|
||||
|
||||
1. **产物识别**:
|
||||
```sh
|
||||
readelf -s sample | grep -iE 'NimMain|nimGC|NimString' | head # ELF;Mach-O 用 llvm-nm
|
||||
readelf -s sample | grep -iE 'nimIncRef|nimDecRef|rawNewString|eqStrings' | head
|
||||
```
|
||||
- Nim 特征:`NimMain`(入口链)、GC 符号(refc 的 `nimGC_*` / orc 的 `nimIncRefCyclic` 等)、`NimStringV2`/`NimStringDesc` 结构类型
|
||||
- 注意:release 构建下 GC 符号常被内联/消除(见坑 1),靠 `NimMain` 与字符串函数兜底
|
||||
- 入口链:C `main` → `NimMain` → `NimMainInner` → `NimMainModule`(模块初始化)→ 业务 main
|
||||
- 模块初始化顺序按依赖拓扑(import 关系):`NimMainModule` 内的初始化段先跑被依赖模块——在初始化段断点/下钻时按调用序对照 import 链
|
||||
|
||||
2. **字符串与序列结构(先判 GC 模式)**:
|
||||
- **orc/arc**(2.x 默认 orc):`NimStringV2 = {len: int, p: ptr NimStrPayload}`;`NimStrPayload = {cap: int, data: 内联字符数组}`——字符串是"len + 堆上 payload 指针",cap 高位带字面量标记位(见 [[layout]])
|
||||
- **refc**(旧默认):`NimStringDesc = {len, reserved, data[]}`——字符内联在结构体里
|
||||
- 定位:`rawNewString`(1.x 与 2.x 均为此 importc 名)分配调用点 → 结构布局 → 字符串操作函数(`eqStrings` 等)
|
||||
- 分析:字符串比较点是关键逻辑(校验/协议/命令分发)——`eqStrings` 调用点即字符串相等判断
|
||||
- 序列(seq)与 string 同构:v2 布局同为 `len + payload 指针`(payload 带 cap),refc 同为 `len/reserved + 内联`——按同一判别表处理
|
||||
- 内存视图(v2 布局,64 位):
|
||||
```
|
||||
栈/对象内: len(int64) | p(ptr) ───────────────┐
|
||||
堆上 payload: cap(int64, bit62=字面量标记) | data[cap+1] ←┘
|
||||
```
|
||||
字符串本体只有 16 字节句柄,内容在独立堆块——分析对象结构时按句柄跳转,别在对象里找字符数据
|
||||
|
||||
3. **内存中定位字符串(动态/转储场景)**:
|
||||
```python
|
||||
# 在内存转储中按 v2 布局找字符串:cap 是 8 字节对齐的容量值,data 后跟可打印 ASCII
|
||||
# 候选: 8 字节对齐的 cap + len 匹配的 data → 反推 NimStringV2 起点
|
||||
```
|
||||
字符串内容在堆上 payload 里,栈上只有 len+指针;先按 `cap` 前缀特征定位 payload,再往回找引用它的 NimStringV2([[examples]] 有完整示例)。
|
||||
|
||||
4. **异常与 raises 路径**:
|
||||
- Nim 2.2.x(Linux x86-64 默认)异常走 goto 式异常表,**无 setjmp 符号**;raise 路径经 `raiseExceptionEx`/`raiseExceptionAux`
|
||||
- 老默认(`--exceptions:setjmp`,Nim 2.0 及以前)用 setjmp/longjmp:`nimSetjmp` 符号可见
|
||||
- 定位:`raiseExceptionEx` 调用点 → 异常对象分配与消息 → catch 分支(异常表驱动)
|
||||
- 分析:异常路径揭示输入校验与失败处理,比正常路径更早暴露边界条件
|
||||
|
||||
5. **GC 与引用计数(按 GC 模式分叉)**:
|
||||
- refc:引用计数 + 周期收集——`nimGC_*`/`nimGCunref`/`nimIncRef`/`nimDecRef` 调用点
|
||||
- orc/arc:ARC 语义——`nimIncRefCyclic`/`nimDecRefIsLastCyclicDyn` 等;显式 inc/dec 少,释放由编译期插入
|
||||
- 分析:GC 调用点帮助识别对象生命周期与所有权(配合字符串结构);release 下内联后改用分配/释放边界推断
|
||||
|
||||
6. **C 混合编译边界**:
|
||||
- `{.compile:}` / `{.importc:}` 混合时 Nim 与 C 符号并存:Nim 侧符号带模块前缀(`hello__u8` 形态)与运行时(NimMain/NimString),C 侧符号无
|
||||
- 边界处是逻辑入口:Nim 业务逻辑在 NimMain 调用链内侧,C 库调用经导入表
|
||||
|
||||
7. **stripped 产物兜底**:
|
||||
```sh
|
||||
strings -n 6 sample | grep -E '@m.*\.nim\.c' | head # C 生成缓存文件名(含模块名,release 也嵌入)
|
||||
strings -n 6 sample | grep -iE 'fatal\.nim|Exception' | head
|
||||
```
|
||||
- `NimMain` 等被 strip 后按特征串(`@m<模块>.nim.c`、std 运行时源文件名)与运行时行为识别([[re-triage]] 初勘兜底);业务源码名不嵌入二进制,别指望它
|
||||
|
||||
## 跨域联合
|
||||
|
||||
- [[re-binary-core]] 网关:本技能归属(选择树「Nim 产物」分支)
|
||||
- [[re-analyze/analysis-contract]]:符号表按数据契约传递
|
||||
- [[re-cpp-abi]]:C 混合侧与无 RTTI 判别参考
|
||||
- [[re-triage]]:初勘兜底(strip 产物按特征串识别)
|
||||
|
||||
## 常见坑与陷阱
|
||||
|
||||
- **GC 版本差异(refc/orc)**:现象——找不到引用计数调用;原因——orc 无显式 inc/dec(ARC 语义)且 release 下 GC 符号内联;对策——先按 Nim 版本与 GC 模式确认再分析,debug/refc 构建符号更全
|
||||
- **NimString 布局随 GC/版本变化**:现象——按 `len/reserved/data` 手写解析器读 2.x 产物全错;原因——2.x orc 默认是 `NimStringV2{len, p}`(payload 带 cap),`len/reserved/data` 内联是 refc 的 NimStringDesc(1.x 默认);对策——先确认产物 GC 模式(见 [[layout]] 判别表)再选布局:debug 构建看 GC 符号(refc 有 `nimGCunref`,orc 有 `nimIncRefCyclic`),release 构建看分配函数命名与 cap 字段是否出现
|
||||
- **导出符号被 strip**:现象——无 NimMain/NimString 符号;原因——strip 处理;对策——按特征字符串/运行时行为识别(步骤 6 兜底)
|
||||
- **C 混合编译**:现象——Nim/C 符号混杂;原因——`{.compile:}` 混合;对策——按符号来源分组,Nim 侧进本技能路径
|
||||
- **字符串比较点误判**:现象——关键校验被当普通比较;原因——eqStrings 包装;对策——追踪 Nim 字符串函数调用点定位比较逻辑
|
||||
- **异常实现代际误判**:现象——按老思路找 nimSetjmp 找不到;原因——2.2+ Linux amd64 默认 goto 式异常(无 setjmp);对策——无 nimSetjmp 时沿 `raiseExceptionEx` 与异常表定位 catch,别当"无异常处理"
|
||||
- **release 内联导致符号稀疏**:现象——debug 能看到的 nimGC_*/eqStrings 在 release 里消失;原因——-d:release 内联;对策——release 产物按行为特征(分配/释放边界、字符串函数调用模式)分析,符号表只是线索不是依据
|
||||
- **字符串内容在堆上,栈上只有句柄**:现象——在栈上按内容搜索字符串找不到;原因——v2 布局的字符数据在独立 payload 堆块里,栈上只有 `len + p` 两个字段;对策——动态/转储场景先按 cap 前缀特征定位 payload 块,再回找引用它的句柄([[examples]] 内存定位示例)
|
||||
- **32 位产物结构尺寸减半**:现象——64 位布局表套 32 位产物偏移全错;原因——NI 在 32 位平台是 4 字节(NimStringV2 为 8 字节而非 16,NimStrPayload cap 为 4 字节);对策——解析前先确认产物位数,按 4/8 字节 NI 选结构尺寸
|
||||
- **非 PIE 老构建入口即固定地址**:现象——`readelf -h` 的 e_entry 是绝对地址(如 0x401xxx),在内存里直接对得上;原因——非 PIE 构建(老默认);对策——入口链定位用符号(NimMain 三连)不依赖 PIE 与否,但换算地址时按 e_type 区分
|
||||
@@ -0,0 +1,126 @@
|
||||
# Nim 最小解析示例
|
||||
|
||||
示例以本机 nim 2.2.10 编译的真实产物为标本(`nim c -d:release --gc:orc`),输出与 Python 解析可逐字段对照。产物结构定义见 [[layout]]。
|
||||
|
||||
## 0. 标本构建
|
||||
|
||||
```nim
|
||||
# hello.nim(含字符串比较、对象、字符串拼接)
|
||||
import std/strutils
|
||||
type Pet = object
|
||||
name: string
|
||||
age: int
|
||||
proc check(s: string): bool =
|
||||
if s == "admin": return true
|
||||
false
|
||||
proc main() =
|
||||
let p = Pet(name: "rex", age: 3)
|
||||
if check(p.name): echo "match: ", p.age
|
||||
else: echo "no: ", p.name & "!"
|
||||
main()
|
||||
```
|
||||
|
||||
```sh
|
||||
nim c -d:release --gc:orc -o:hello_orc hello.nim # orc(2.x 默认)
|
||||
nim c --gc:refc -o:hello_refc hello.nim # refc(对照)
|
||||
```
|
||||
|
||||
## 1. 符号对照(release 构建)
|
||||
|
||||
```
|
||||
$ nm hello_orc | grep -iE 'NimMain|newString|eqStrings'
|
||||
000000000000be10 T NimMain ← 入口链(C main → NimMain → NimMainInner → NimMainModule)
|
||||
000000000000bdf0 T NimMainInner
|
||||
000000000000be30 T NimMainModule
|
||||
0000000000008110 t rawNewString ← 字符串分配(1.x 与 2.x 均为此 importc 名)
|
||||
```
|
||||
|
||||
对照要点:release 下 `nimGC_*`/`eqStrings` 被内联(nm 无输出是正常现象,见 SKILL.md 坑 1/7);`NimMain*` 与 `rawNewString` 是稳定锚点。debug 构建(`nim c --gc:orc`)可见 `eqStrings`、`nimIncRefCyclic`、`nimDecRefIsLastCyclicDyn`;refc 构建可见 `nimGC_setStackBottom`、`nimGCunref`、`nimGCvisit`——GC 模式判别直接看这些符号有无(判别表见 [[layout]])。
|
||||
|
||||
## 2. 字符串布局验证(生成 C 结构,实测)
|
||||
|
||||
```
|
||||
$ grep -A6 'struct NimStringV2' 生成缓存目录/@mhello.nim.c
|
||||
struct NimStringV2 {
|
||||
NI len;
|
||||
NimStrPayload* p;
|
||||
};
|
||||
struct NimStrPayload {
|
||||
NI cap;
|
||||
NIM_CHAR data[SEQ_DECL_SIZE]; /* 内联字符 */
|
||||
};
|
||||
```
|
||||
|
||||
对照要点:orc 产物字符串是 `len + payload 指针`(payload = cap + 内联数据),**不是** 1.x refc 的 `len/reserved/data` 内联——手写解析器必须先按 GC 模式选布局([[layout]] 判别表)。cap 的 bit 62(64 位)为字面量标记 strlitFlag。
|
||||
|
||||
## 3. Python 解析 NimStringV2(内存视图,最小示例)
|
||||
|
||||
```python
|
||||
import struct
|
||||
|
||||
# 模拟 Nim 对象布局:Pet = { name: NimStringV2, age: int }
|
||||
# NimStringV2 = { len: int64, p: ptr }(orc 布局,64 位小端)
|
||||
|
||||
def read_nimstr_v2(buf, off):
|
||||
ln, p = struct.unpack_from('<QQ', buf, off)
|
||||
if p == 0 or ln == 0:
|
||||
return '' if ln == 0 else '(nil payload!)'
|
||||
cap, = struct.unpack_from('<Q', buf, p)
|
||||
data = buf[p+8 : p+8+ln]
|
||||
return data.decode('utf-8', 'replace')
|
||||
|
||||
# 用途:在转储中定位 NimStringV2(len 字段与 payload 里的 cap/data 互相印证),
|
||||
# 还原字符串即找到校验/命令分发点。refc 布局改为内联读取:
|
||||
def read_nimstr_desc(buf, off):
|
||||
ln, reserved = struct.unpack_from('<QQ', buf, off)
|
||||
return buf[off+16 : off+16+ln].decode('utf-8', 'replace')
|
||||
```
|
||||
|
||||
对照要点:v2 布局下字符串内容在堆上(payload),栈上只有 len+指针;搜索字符串时按 `cap` 前缀特征(对齐的容量值)比按内容更可靠。
|
||||
|
||||
## 4. 异常实现对照(2.2.10,Linux x86-64)
|
||||
|
||||
```
|
||||
$ nim c --gc:orc -o:exc_nim exc.nim # 含 try/except 的程序
|
||||
$ nm exc_nim | grep -iE 'setjmp|raiseException|personality'
|
||||
00000000000075db t raiseExceptionAux__system_u4320
|
||||
00000000000076db t raiseExceptionEx
|
||||
# 无 nimSetjmp、无 __gxx_personality_v0 —— goto 式异常(无 setjmp)
|
||||
$ readelf -S exc_nim | grep -E 'except_table|eh_frame'
|
||||
[15] .eh_frame_hdr
|
||||
[16] .eh_frame # 有 unwind 信息但无 .gcc_except_table
|
||||
|
||||
# 对照:--exceptions:setjmp 构建
|
||||
$ nim c --gc:orc --exceptions:setjmp -o:exc_nim_sj exc.nim
|
||||
$ grep -c setjmp 生成缓存目录/@mexc.nim.c
|
||||
3 # setjmp 调用出现 = 老式异常
|
||||
```
|
||||
|
||||
对照要点:2.2 默认产物"有异常处理但无 setjmp 符号";`nimSetjmp` 只在老默认/显式 `--exceptions:setjmp` 下出现。raise 路径锚点是 `raiseExceptionEx`。
|
||||
|
||||
## 5. 字节样例(入口与特征串)
|
||||
|
||||
```
|
||||
$ xxd -l 32 hello_orc | head -2
|
||||
00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
|
||||
00000010: 0300 3e00 0100 0000 9011 0000 0000 0000 ..>.............
|
||||
e_type=03(DYN/PIE) e_machine=003e(x86-64) e_entry=0x1190
|
||||
|
||||
$ strings -n 6 hello_orc | grep -E '\.nim' | sort -u
|
||||
@mhello.nim.c ← C 代码生成缓存文件名(含模块名,release 也嵌入)
|
||||
@psystem.nim.c @pstd@sprivate@sdigitsutils.nim.c ← 运行时模块
|
||||
fatal.nim ← std 运行时源文件名
|
||||
```
|
||||
|
||||
对照要点:Nim 产物嵌入的 `.nim` 特征串是 `@m<模块>.nim.c`(C 缓存名)与 std 模块源文件名,不含业务源码名——stripped 兜底按 `@m*.nim.c` 匹配模块列表。
|
||||
|
||||
## 实现教训(内化)
|
||||
|
||||
- 先判 GC 模式再选字符串/GC 布局:判别表见 [[layout]],符号判据用 debug 构建,release 用行为特征
|
||||
- `NimMain*` 三连与 `rawNewString`/`eqStrings` 是跨版本稳定锚点,符号定位从它们出发
|
||||
- 异常"无 setjmp"不代表无异常处理:2.2+ 默认 goto 式,锚点改 `raiseExceptionEx`
|
||||
|
||||
## 使用注意
|
||||
|
||||
- 静态分析无需沙箱;本机 nim 2.2.10 实测输出与用户产物的差异以产物自身符号为准
|
||||
- 与 [[re-analyze/analysis-contract]](符号表传递)、[[re-triage]](初勘兜底)配合使用
|
||||
@@ -0,0 +1,86 @@
|
||||
# Nim 二进制布局:入口链 / 字符串结构 / GC 与异常实现
|
||||
|
||||
Nim 产物是 C 代码生成 + 运行时库链接:入口链、字符串布局、GC 与异常实现都随编译器版本与 GC 模式变化。先确认"版本 + GC 模式"再选布局是分析前提。
|
||||
|
||||
## 入口链(ELF,Linux 默认 C 后端)
|
||||
|
||||
```
|
||||
C main
|
||||
└─ NimMain (运行时初始化:GC 启动、堆栈底部设置)
|
||||
└─ NimMainInner
|
||||
└─ NimMainModule (各模块初始化:全局变量构造、模块级代码)
|
||||
└─ 业务 main(用户定义的 main 过程)
|
||||
```
|
||||
|
||||
- 符号形态(实测 nim 2.2.10):`NimMain`/`NimMainInner`/`NimMainModule` 均为导出函数;`main` 是 C 入口
|
||||
- 模块级函数名带模块前缀与哈希后缀:`main__hello_u8`、`check__hello_u5`(`<proc>__<module>_<id>` 形态)
|
||||
- 字符串等运行时类型以 C struct 形态存在于调试类型:`NimStringV2`/`NimStrPayload`(stripped 后消失,靠布局表恢复)
|
||||
|
||||
## 字符串结构(按 GC 模式分叉)
|
||||
|
||||
### orc/arc(2.x 默认 orc;实测 2.2.10 生成的 C 结构)
|
||||
|
||||
```c
|
||||
struct NimStringV2 { /* 8/16 字节(64 位):len + 指针 */
|
||||
NI len; /* 字节长度(不含结尾 \0) */
|
||||
NimStrPayload* p; /* 堆上 payload;len==0 时可 nil(字面量 p 指向静态区) */
|
||||
};
|
||||
struct NimStrPayload {
|
||||
NI cap; /* 容量;cap 高位 bit(62) 为 strlitFlag(字面量标记) */
|
||||
NIM_CHAR data[]; /* 内联字符数组 */
|
||||
};
|
||||
```
|
||||
|
||||
- `strlitFlag = 1 shl (sizeof(int)*8 - 2)`(64 位下 bit 62):cap 带此位 = 字符串字面量(静态区,不可变)
|
||||
- 分配函数:`rawNewString`(1.x 与 2.x 均为此 importc 名,实测 1.6 与 2.2 一致)
|
||||
- 内存图:`NimStringV2` 可内联在栈/对象里,payload 独立堆分配(含 cap 前缀)
|
||||
|
||||
### refc(1.x 默认与 2.x --gc:refc;NimStringDesc)
|
||||
|
||||
```c
|
||||
struct NimStringDesc { /* len/reserved + 内联字符 */
|
||||
NI len;
|
||||
NI reserved; /* 已分配容量(高位带 seqShallowFlag/strlitFlag 标记) */
|
||||
NIM_CHAR data[]; /* 内联 */
|
||||
};
|
||||
```
|
||||
|
||||
- 字符串本体即结构体,无独立 payload;`NimString = ptr NimStringDesc`
|
||||
|
||||
### 判别表(先判 GC 模式再选布局)
|
||||
|
||||
| 判别线索 | orc/arc(v2 字符串) | refc(NimStringDesc) |
|
||||
|---|---|---|
|
||||
| 编译默认 | Nim 2.x 默认 | Nim 1.x 默认 / 2.x 显式 `--gc:refc` |
|
||||
| GC 符号(debug) | `nimIncRefCyclic` `nimDecRefIsLastCyclicDyn` | `nimGC_setStackBottom` `nimGCunref` `nimGCvisit` |
|
||||
| 字符串分配函数 | `rawNewString`(2.x) | `rawNewString`(1.x 经 `newStringOfCap` importc,同名) |
|
||||
| 字符串比较 | `eqStrings`(两者都有,debug 可见) | 同左 |
|
||||
|
||||
## GC 与所有权
|
||||
|
||||
- refc:引用计数 + 周期收集(nimGC_* 家族);显式 inc/dec 调用点多
|
||||
- orc/arc:ARC 语义 + 周期收集(`nimIncRefCyclic`/`nimDecRefIsLastCyclicDyn`);retain/release 由编译器在赋值/作用域边界插入,无显式计数器
|
||||
- release 构建(-d:release)下 GC 辅助函数常内联消除——符号表在 debug 构建完整,release 靠行为特征
|
||||
|
||||
## 异常实现(版本差异大)
|
||||
|
||||
| 版本/开关 | 机制 | 可见符号 |
|
||||
|---|---|---|
|
||||
| Nim 2.2.x 默认(Linux x86-64,orc) | goto 式异常表(--exceptions:goto) | 无 setjmp;`raiseExceptionEx`/`raiseExceptionAux` |
|
||||
| 老默认(--exceptions:setjmp,Nim 2.0 及以前) | setjmp/longjmp | `nimSetjmp` |
|
||||
| --exceptions:cpp | C++ 异常(C++ 后端) | __cxa_throw 等 |
|
||||
|
||||
- 实测(2.2.10 orc):二进制含 `.eh_frame` 但无 `.gcc_except_table`、无 `__gxx_personality_v0`、无 setjmp——"有异常处理但看不见 setjmp"是 2.2+ 的常态
|
||||
- 定位 catch:从 `raiseExceptionEx` 调用点回看异常表/分支结构;异常对象含类型字段(Nim 异常是引用对象,首字段类型指针)
|
||||
|
||||
## 版本演进要点
|
||||
|
||||
- 1.x:默认 refc + NimStringDesc + setjmp 异常
|
||||
- 2.0.x:orc 成为默认 GC,strs_v2(v2 字符串)随 orc 启用;`--gc:refc` 仍是老布局
|
||||
- 2.2.x:Linux amd64 默认 goto 式异常(无 setjmp 符号);`rawNewString` 取代 `newString1` 命名
|
||||
- 跨版本复用的方法:入口链定位、字符串比较点追踪、异常路径还原;不复用的:具体符号名、结构偏移
|
||||
|
||||
## 使用注意
|
||||
|
||||
- 静态分析无需沙箱;Nim 产物跨平台(Linux ELF / Windows PE / macOS Mach-O),符号形态一致(C 后端)
|
||||
- 与 [[re-analyze/analysis-contract]](符号表传递)、[[re-cpp-abi]](C 混合侧)配合使用
|
||||
Reference in New Issue
Block a user