@@ -29,6 +29,20 @@ grep -rn "openkal ─── BEGIN" llvm/
2929
3030## 已替换
3131
32+ ⭐ 五处,四个文件,一个判据 —— 每一处都能填进上面那句话。
33+
34+ ``` sh
35+ grep -rn " openkal ─── BEGIN" llvm/ # 10 处标记(含配对的 #else/#endif)
36+ ```
37+
38+ | 文件 | 上游按什么分派 | 平台面 | openkal 的答案 |
39+ | ---| ---| ---| ---|
40+ | ` libcxx/src/atomic.cpp ` | 四个 OS | 挂起/唤醒 | ` kal_task_wait ` / ` kal_task_wake ` |
41+ | ` libunwind/src/AddressSpace.hpp ` | ` _WIN32 ` | ** 这个镜像的展开表在哪** | 镜像自己知道:` __ImageBase ` + 段表 |
42+ | ` libunwind/src/RWMutex.hpp ` | ` _WIN32 ` | 读写锁 | pthread ⇒ musl ⇒ ` kal_task_* ` |
43+ | ` libunwind/src/UnwindCursor.hpp ` | ` _WIN32 ` | (无) | 整段没被用到,只是被 include |
44+ | ` compiler-rt/…/emutls.c ` | ` _WIN32 ` | 互斥 + 对齐分配 | pthread + ` posix_memalign ` |
45+
3246### ` libcxx/src/atomic.cpp ` — ` std::atomic ` 的等待与唤醒
3347
3448上游一条链,五个分支,四个操作系统:
@@ -57,6 +71,82 @@ openkal 的答案是 `kal_task_wait` / `kal_task_wake` —— 规范管它叫**
5771唤醒),以及 ` -1 ` 表示「全部唤醒」(上游写作 ` INT_MAX ` ,openkal 的计数是
5872` kal_uintptr ` ,所以按回绕写)。
5973
74+ ### ⭐⭐ ` libunwind/src/AddressSpace.hpp ` — 这个镜像的展开表在哪
75+
76+ 上游按 OS 答:` EnumProcessModules ` 枚举进程的全部模块,逐个解析 PE 头找
77+ ` .eh_frame ` 。** 而这个问题这份文件已经答过三遍,没有一遍问操作系统** :
78+
79+ | 目标 | 怎么答的 |
80+ | ---| ---|
81+ | 裸机 | 链接器脚本定义的 ` __eh_frame_start ` / ` __eh_frame_end ` |
82+ | Darwin | ` _dyld_find_unwind_sections ` (` openkal-macos ` 用链接器的 ` section$start$ ` 实现) |
83+ | ELF | 自己的 program headers |
84+ | ** PE(上游)** | ⚠️ 让操作系统枚举模块 |
85+
86+ ⇒ openkal 的答案和前三条同一句话:** 镜像自己知道** 。静态链接的 openkal 程序
87+ 只有一个模块,基址是链接器定义的符号 ` __ImageBase ` (不是调用),段表在离它固定
88+ 的偏移上。读它是** 目标格式** 的知识 —— 展开器本来就是由这种知识构成的 —— 不是
89+ 系统调用,也不是操作系统。
90+
91+ ⚠️ ** 而台账原先写着这一支「已由 DWARF 路线绕开」,那是凭读守卫写的,实测否掉了。**
92+ ` _WIN32 && DWARF ` 正是它的守卫,DWARF 路线就是它。2026-08-23 实测:
93+
94+ ```
95+ AddressSpace.hpp:114 → /usr/x86_64-w64-mingw32/include/windows.h:69
96+ → winnt.h:1658 → x86intrin.h → mm_malloc.h:43
97+ error: use of undeclared identifier '__mingw_aligned_malloc'
98+ ```
99+
100+ —— 一条 include 把** 宿主的 mingw sysroot** 拉进了刚刚摆脱了厂商 SDK 的构建。
101+
102+ ⭐ 实测确认段表里找得到:链接后的镜像里是 ` .eh_fram ` (PE 的段名字段固定 8 字节,
103+ ` .eh_frame ` 是 9 个字符),大小 0x530c8 —— 这正是上游用
104+ ` IMAGE_SIZEOF_SHORT_NAME ` 比 8 个字节而不是比全名的原因。
105+
106+ ⚠️ ** 走过一条错路,记下来免得再走** :先试过用 COFF 的分组段
107+ (` .eh_frame$a ` / ` .eh_frame$z ` )去夹住 ` .eh_frame ` ,链接器的排序是
108+
109+ ```
110+ .eh_frame 0x00 0x58 ← 真正的帧
111+ .eh_frame$a 0x58 0x01 ← "start" 落在它们后面
112+ .eh_frame$z 0x59 0x01 ⇒ end-start = 1 字节
113+ ```
114+
115+ ** 不带 ` $ ` 的段排在最前** ,所以那个方案会给展开器一个空区间 —— 不是链接失败,
116+ 是** 静默的错答案** 。
117+
118+ ### ` libunwind/src/RWMutex.hpp ` — 读写锁
119+
120+ ⚠️ 两处,而不是一处:` <windows.h> ` 的 include 在 ` _LIBUNWIND_HAS_NO_THREADS `
121+ ** 之前** 就无条件发生,类的选择是第二处。只撤回第一处会留下引用 ` SRWLOCK ` 而没有
122+ 任何东西声明它。
123+
124+ ### ` libunwind/src/UnwindCursor.hpp ` — 一处纯粹没被用到的 include
125+
126+ 这份文件里所有需要 Windows 类型的代码都在 ` _LIBUNWIND_SUPPORT_SEH_UNWIND ` 下,
127+ 而 openkal 用 ` -fdwarf-exceptions ` 。⇒ include 被执行,它声明的东西一个都没用上,
128+ 而它拉进来的是宿主的 mingw sysroot。
129+
130+ ### ` compiler-rt/lib/builtins/emutls.c ` — 互斥与对齐分配
131+
132+ ⚠️ ** 这个文件被编译到 PE 上,恰恰是因为那个平台自己的 thread-local 机制用不了**
133+ (` _tls_index ` 需要动态加载器),然后它转身去要了同一个平台的 C 运行时:
134+
135+ ```
136+ corecrt.h:98: typedef redefinition with different types
137+ emutls.c:164: call to undeclared function '_aligned_malloc'
138+ ```
139+
140+ ---
141+
142+ ## ⭐ 一个名字,不是五个
143+
144+ 五处补丁全部守卫在 ** ` OPENKAL ` ** 上,` cflags ` 和 ` cxxflags ` 各给一次
145+ (` compiler-rt ` 是 C)。读法是「在 Windows 上,除非底下是 openkal」。
146+
147+ ⚠️ 一度写成 ` _LIBUNWIND_OPENKAL ` ,随后 ` emutls.c ` 需要同一个事实而它是 C 文件 ——
148+ ** 同一个事实两个名字** 正是这套代码里反复出问题的形状,所以收敛掉了。
149+
60150---
61151
62152## 不需要动的 —— 而这一节比上一节重要
@@ -67,7 +157,8 @@ openkal 的答案是 `kal_task_wait` / `kal_task_wake` —— 规范管它叫**
67157| ---| ---| ---|
68158| ` _LIBCPP_WIN32API ` | ** 12** | ✅ ` port/include/__config ` 撤回了它 → ** 自己落到 POSIX 分支** |
69159| ` __SEH__ ` / ` _LIBUNWIND_SUPPORT_DWARF_UNWIND ` | 2 | ✅ ` -fdwarf-exceptions ` ,异常机制跟随我们带的 unwinder |
70- | 裸 ` _WIN32 ` | 3 | 1 处已换(见上),2 处待办(见下) |
160+ | 裸 ` _WIN32 ` | 3 | ✅ 三处全换(AddressSpace / RWMutex / UnwindCursor) |
161+ | ` emutls.c ` 的 ` _WIN32 ` | 2 | ✅ 走 POSIX 分支 |
71162
72163⭐⭐ ** 12 处不用换,因为 libc++ 的 POSIX 分支本来就已经在 openkal 上了。** 它调
73164` fopen ` / ` clock_gettime ` / ` pthread_* ` ,那些是 musl,而 musl 就在 openkal 上。
@@ -78,12 +169,18 @@ openkal 的答案是 `kal_task_wait` / `kal_task_wake` —— 规范管它叫**
78169
79170---
80171
81- ## 待办
172+ ## ⚠️ 不在这里的两类东西
82173
83- | 文件 | 平台面 | openkal 的答案 |
174+ 一开始误以为要在这棵树里解决,实际不在:
175+
176+ | | 归谁 | 为什么 |
84177| ---| ---| ---|
85- | ` libunwind/src/RWMutex.hpp ` | 读写锁 | ` openkal.task ` ;或 ` _LIBUNWIND_HAS_NO_THREADS ` (unwinder 的锁只在缓存上) |
86- | ` libunwind/src/AddressSpace.hpp ` | 段查询的 Windows 分支 | 已由 DWARF 路线绕开,待确认没有残留 |
178+ | 数据模型(` sizeof(long) ` ) | ** C 库** (` musl-generated/<arch>[-<os>] ` ) | 它重建的是 POSIX,而 POSIX 自己命名了 ` long ` 。openkal 接口上不存在这个问题 —— 见 openkal 的 §1.3 |
179+ | ` -fdwarf-exceptions ` / ` -femulated-tls ` | ** mcpp** (` graph_runtime_compile_flags ` ) | 它们决定 ` throw ` 和 ` thread_local ` ** 编译成什么** ,所以是** 整张图** 的性质,不是某个包的。写在本包 ` [build] ` 里时,只覆盖了本包的对象,使用者的 ` main.o ` 拿不到 |
180+
181+ ⚠️ 第二行是实测逼出来的:全部编过之后,链接报
182+ ` undefined symbol: __gxx_personality_seh0 ` ,引用它的是** 使用者的 ` main.o ` ** ——
183+ 一个写了 ` try ` 而没有任何理由知道这件事的翻译单元。
87184
88185---
89186
0 commit comments