Skip to content

Commit 814b3ab

Browse files
committed
feat(port): PE 目标打通 —— 展开表、锁、TLS 三处都问了「哪个 OS」
同一份 src/main.cpp 现在从一台 Linux 宿主构建出四个目标,并且两个能在本机跑的 输出逐字相同: x86_64-linux-gnu 静态 ELF ✅ 跑通 x86_64-windows-gnu PE32+ ✅ 跑通(wine 冒烟,⚠️ 不等于 Windows) aarch64-macos Mach-O arm64 ✅ 产出 riscv64-none-elf RISC-V ELF ✅ 产出 sorted: 2 4 7 / caught: 42 / unwound: true / import std over openkal: ok ⭐ unwound: true 是判据 —— 析构函数在展开中跑到了,说明 libunwind 靠自读镜像 找到了 .eh_frame,而不是靠 EnumProcessModules。 ── 三处 <windows.h>,一个形状 ────────────────────────────── ⭐⭐ AddressSpace.hpp 问「这个镜像的展开表在哪」,上游答「让操作系统枚举模块」。 而这份文件已经答过这个问题三遍,没有一遍问 OS:裸机读链接器符号,Darwin 读 _dyld_find_unwind_sections,ELF 读自己的 program headers。openkal 的答案和它们 同一句话 —— 镜像自己知道:__ImageBase 是链接器定义的符号(不是调用),段表在离 它固定的偏移上。 ⚠️ 而 PATCHES.md 原先写着这一支「已由 DWARF 路线绕开」—— 凭读守卫写的,实测 否掉了:_WIN32 && DWARF 正是它的守卫。修好它,同样的错误挪到 UnwindCursor.hpp (一处纯粹没被用到的 include),再挪到 RWMutex.hpp。 ⚠️ RWMutex 里同一个事实说了两遍(include 一处、class 一处),两处一起改。 ⚠️ 走过一条错路并记进台账:先试 COFF 分组段 .eh_frame$a/$z 夹住 .eh_frame, 实测链接器把不带 $ 的段排在最前 ⇒ start 落在数据之后,end-start=1 字节。那不是 链接失败,是静默的错答案。 ── emutls:第三种格式,同一堵墙 ──────────────────────────── PE 的 _tls_index 和 Mach-O 的 _tlv_bootstrap 都由动态加载器 bootstrap,而自包含 的 openkal 镜像没有加载器。macOS 上已经用 -femulated-tls + 编 emutls.c 解过一次; Windows 是它在第三种格式里的同一件事。 ⚠️ emutls.c 自己又问了一次「哪个 OS」,于是被编译到 PE 上的原因(平台的 TLS 用 不了)和它的行为(去要平台的 C 运行时)自相矛盾。走 POSIX 分支。 ── 一个名字,不是五个 ────────────────────────────────── 五处补丁统一守卫在 OPENKAL 上,cflags/cxxflags 各给一次(compiler-rt 是 C)。 ⚠️ 一度写成 _LIBUNWIND_OPENKAL,随后 emutls.c 需要同一个事实 —— 同一个事实两个 名字正是这套代码反复出问题的形状。 ── 另外三处不是「移植」而是「配置」 ──────────────────────── 1. __config_site 的线程 API:四个全写 0 不是「没有线程 API」,是「没人回答」, libc++ 于是按 OS 自选 —— ELF/Mach-O 上碰巧选对 pthread,PE 上选了 WIN32, 报 undefined symbol: std::__1::__libcpp_mutex_lock(void**)(void** 是 Win32 的形状)。⚠️ port/include/__config 撤回 _LIBCPP_WIN32API 修不了它,因为撤回 发生在 __config 已经据此下了结论之后 —— 该文件记录的「结论的结论」第三例。 2. operator new/delete 定义了两遍。libcxx/src/new.cpp 自己写着「以下代码原样 拷贝进 libcxxabi/src/stdlib_new_delete.cpp,本文件这份是权威的」。上游把两者 建成两个库,本包建成一个 ⇒ 同一条链接线上各来一份。 ⚠️ 三个目标看不见:两份都是弱符号,ELF/Mach-O 上重复的弱定义正是「弱」的 含义,链接器挑一个并且不说话。COFF 报了 30 条。⇒ 包级排除,不是 cfg(windows) 排除 —— 第三种格式没有制造这个重复,它只是报告了它。 3. -fdwarf-exceptions / -femulated-tls 从本包 [build] 里撤走,改由 mcpp 全图 推导 —— 见 mcpp 的 graph_runtime_compile_flags。它们决定 throw 和 thread_local 编译成什么,是整张图的性质。写在包里时只覆盖了本包的对象, ⚠️ 实测:全部编过之后链接报 undefined symbol: __gxx_personality_seh0, 引用它的是使用者的 main.o。 ── 例子清单 ─────────────────────────────────────────── examples/same-source 的 [toolchain] default 从 llvm@22.1.8 改成 openkal-llvm@22.1.8。⚠️ 同一个载荷、同一个 clang、同一个版本 —— 差别在 mcpp 据此相信目标侧从哪来。写成 llvm 时四个目标只成两个,而两条报错都没提到工具链族。
1 parent a22f149 commit 814b3ab

8 files changed

Lines changed: 362 additions & 17 deletions

File tree

examples/same-source/mcpp.toml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,23 @@ runner = ["qemu-system-riscv64", "-machine", "virt", "-nographic",
3636
[dependencies]
3737
openkal-llvm-runtime = { path = "../.." }
3838

39+
# ⭐⭐ THE ONE LINE THAT MAKES EVERY TARGET REACHABLE, AND IT IS THE FAMILY NAME
40+
# THAT DOES IT RATHER THAN THE VERSION.
41+
#
42+
# `openkal-llvm` downloads nothing `llvm` does not — it is the same payload, the
43+
# same clang, the same version. What differs is what mcpp then believes about
44+
# where the target side comes from: under `llvm`, from the payload built for
45+
# THIS machine; under `openkal-llvm`, from the graph.
46+
#
47+
# ⚠️ Measured 2026-08-23 with `default = "llvm@22.1.8"` here, which is what this
48+
# file said until now, and which built two of the four targets:
49+
#
50+
# --target x86_64-windows-gnu → x86_64-w64-mingw32-g++ … __config: No such file
51+
# --target aarch64-macos → "no toolchain payload exists that runs here"
52+
#
53+
# Neither message mentions a toolchain family, and both are true of `llvm`: the
54+
# payload really does have no macOS cross driver, and mingw really is the only
55+
# thing here that emits PE. ⇒ The build did not fail to find the openkal path,
56+
# it was never asked for it. One word, and the same source reaches all four.
3957
[toolchain]
40-
default = "llvm@22.1.8"
58+
default = "openkal-llvm@22.1.8"

llvm-generated/generic/__config_site

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,28 @@
1717
#define _LIBCPP_HAS_MONOTONIC_CLOCK 1
1818
#define _LIBCPP_HAS_TERMINAL 1
1919
#define _LIBCPP_HAS_MUSL_LIBC 1
20-
#define _LIBCPP_HAS_THREAD_API_PTHREAD 0
20+
// ⭐⭐ STATED, NOT LEFT TO libc++ TO GUESS FROM THE OPERATING SYSTEM.
21+
//
22+
// All four of these were 0, which is not "no thread API" — it is "nobody
23+
// answered", and `__config` then answers for itself by naming operating
24+
// systems: __linux__ / __APPLE__ / … → pthreads, `_LIBCPP_WIN32API` → Win32.
25+
// On ELF and on Mach-O that guess lands on pthreads and is right by accident.
26+
//
27+
// ⚠️ AND THE `__config` OVERLAY CANNOT CORRECT IT. `port/include/__config`
28+
// withdraws `_LIBCPP_WIN32API`, but it does so AFTER `#include_next <__config>`
29+
// has already drawn this conclusion from it — the same "conclusion drawn from
30+
// the conclusion" that `_LIBCPP_HAS_OPEN_WITH_WCHAR` is, and the third instance
31+
// of it in that file. Measured 2026-08-23, linking for `x86_64-windows-gnu`:
32+
//
33+
// undefined symbol: std::__1::__libcpp_mutex_lock(void**)
34+
//
35+
// `void**`, not `pthread_mutex_t*` — the Win32 shape, whose definitions live in
36+
// `src/support/win32/thread_win32.cpp`, which this package does not build
37+
// because on openkal there is no Win32 threading to build against.
38+
//
39+
// ⇒ openkal's answer is one answer for every target: pthreads, because musl is
40+
// beneath on every one of them, and musl's pthreads are `kal_task_*`.
41+
#define _LIBCPP_HAS_THREAD_API_PTHREAD 1
2142
#define _LIBCPP_HAS_THREAD_API_EXTERNAL 0
2243
#define _LIBCPP_HAS_THREAD_API_WIN32 0
2344
#define _LIBCPP_HAS_THREAD_API_C11 0 // FIXME: Is this guarding dead code?

llvm/PATCHES.md

Lines changed: 102 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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

llvm/compiler-rt/lib/builtins/emutls.c

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,21 @@ typedef struct emutls_address_array {
4545

4646
static void emutls_shutdown(emutls_address_array *array);
4747

48-
#ifndef _WIN32
48+
/* ─── openkal ─── BEGIN
49+
* The platform surface here is a mutex and an aligned allocation, and upstream
50+
* picks them by operating system: CRITICAL_SECTION + `_aligned_malloc` on
51+
* `_WIN32`, pthreads + `posix_memalign` elsewhere. openkal makes the question
52+
* have one answer on every target, because musl is beneath every one of them.
53+
*
54+
* ⚠️ Measured 2026-08-23 — this file is compiled for PE precisely BECAUSE the
55+
* platform's own thread-local mechanism is unavailable (`_tls_index` needs a
56+
* dynamic loader), and then it reached for that same platform's C runtime:
57+
*
58+
* corecrt.h:98: typedef redefinition with different types
59+
* emutls.c:164: call to undeclared function '_aligned_malloc'
60+
*
61+
* ─── openkal ─── END */
62+
#if !defined(_WIN32) || defined(OPENKAL)
4963

5064
#include <pthread.h>
5165

@@ -374,7 +388,9 @@ emutls_get_address_array(uintptr_t index) {
374388
return array;
375389
}
376390

377-
#ifndef _WIN32
391+
/* ─── openkal ─── BEGIN (同上) */
392+
#if !defined(_WIN32) || defined(OPENKAL)
393+
/* ─── openkal ─── END */
378394
// Our emulated TLS implementation relies on local state (e.g. for the pthread
379395
// key), and if we duplicate this state across different shared libraries,
380396
// accesses to the same TLS variable from different shared libraries will yield

llvm/libunwind/src/AddressSpace.hpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,8 +111,41 @@ extern char __exidx_end;
111111

112112
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
113113

114+
// ─── openkal ─── BEGIN
115+
//
116+
// ⭐⭐ THE QUESTION HERE IS "WHERE ARE THIS IMAGE'S UNWIND TABLES", AND UPSTREAM
117+
// ANSWERS IT BY ASKING THE OPERATING SYSTEM TO ENUMERATE THE PROCESS'S MODULES.
118+
//
119+
// This file already answers the same question three other ways, and none of
120+
// them asks an OS: bare metal reads symbols the linker defined, Darwin reads
121+
// `_dyld_find_unwind_sections` (which `openkal-macos` implements out of the
122+
// linker's `section$start$__TEXT$__eh_frame`), and ELF reads its own program
123+
// headers. Only this branch reaches for `EnumProcessModules`.
124+
//
125+
// ⚠️ AND THE LEDGER SAID THIS BRANCH WAS ALREADY AVOIDED. `PATCHES.md` recorded
126+
// it as "已由 DWARF 路线绕开" — written from reading the guards rather than from
127+
// a build. Measured 2026-08-23, cross-compiling `x86_64-windows-gnu`:
128+
//
129+
// AddressSpace.hpp:114 → /usr/x86_64-w64-mingw32/include/windows.h:69
130+
// → winnt.h:1658 → x86intrin.h → mm_malloc.h:43
131+
// error: use of undeclared identifier '__mingw_aligned_malloc'
132+
//
133+
// The DWARF route is not the one that avoids this branch — `_WIN32 && DWARF` is
134+
// its exact guard. And the include pulled the HOST's mingw sysroot into a build
135+
// that had just been freed of any vendor SDK.
136+
//
137+
// ⇒ openkal's answer is the one this file already gives twice: the image knows.
138+
// A statically linked openkal program is one module, its base is a symbol the
139+
// linker defines (`__ImageBase`, no call), and its section table is at a fixed
140+
// offset from that base. Reading it is object-format knowledge, which is what
141+
// an unwinder is made of — it is not a system call, and it is not an OS.
142+
#if defined(OPENKAL)
143+
extern "C" char __ImageBase[];
144+
#else
114145
#include <windows.h>
115146
#include <psapi.h>
147+
#endif
148+
// ─── openkal ─── END
116149

117150
#elif defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) || \
118151
defined(_LIBUNWIND_USE_DL_UNWIND_FIND_EXIDX)
@@ -557,6 +590,57 @@ inline bool LocalAddressSpace::findUnwindSections(
557590
if (info.arm_section && info.arm_section_length)
558591
return true;
559592
#elif defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) && defined(_WIN32)
593+
// ─── openkal ─── BEGIN
594+
#if defined(OPENKAL)
595+
// The same walk upstream does, over one module instead of every module, and
596+
// reaching it through a linker-defined symbol instead of through the OS.
597+
//
598+
// ⚠️ FIELDS ARE READ AT THEIR OFFSETS RATHER THAN THROUGH `IMAGE_*` STRUCTS,
599+
// because those structs are what `<windows.h>` was being included for. PE
600+
// fixes every offset below by specification, and they do not vary with the
601+
// data model — which is why they are exact-width types and not `long`.
602+
{
603+
const uint8_t *base = reinterpret_cast<const uint8_t *>(__ImageBase);
604+
auto u16 = [](const uint8_t *p) {
605+
uint16_t v; __builtin_memcpy(&v, p, sizeof(v)); return v;
606+
};
607+
auto u32 = [](const uint8_t *p) {
608+
uint32_t v; __builtin_memcpy(&v, p, sizeof(v)); return v;
609+
};
610+
611+
const uint8_t *nt = base + u32(base + 0x3c); // IMAGE_DOS_HEADER::e_lfanew
612+
const uint16_t nsec = u16(nt + 4 + 2); // FileHeader::NumberOfSections
613+
const uint16_t optSize = u16(nt + 4 + 16); // FileHeader::SizeOfOptionalHeader
614+
const uint8_t *sec = nt + 4 + 20 + optSize;
615+
616+
bool found_obj = false;
617+
bool found_hdr = false;
618+
info.dso_base = (uintptr_t)base;
619+
for (uint16_t j = 0; j < nsec; ++j, sec += 40) { // sizeof(SECTION_HEADER)
620+
const uintptr_t begin = (uintptr_t)base + u32(sec + 12); // VirtualAddress
621+
const uintptr_t end = begin + u32(sec + 8); // Misc.VirtualSize
622+
// ⚠️ EIGHT BYTES, AND `.eh_frame` IS NINE CHARACTERS. A PE section name
623+
// is a fixed 8-byte field, so the linked image carries `.eh_fram`. This
624+
// is upstream's comparison length (`IMAGE_SIZEOF_SHORT_NAME`) and the
625+
// reason it is not a mistake.
626+
if (!strncmp((const char *)sec, ".text", 8)) {
627+
if (targetAddr >= begin && targetAddr < end)
628+
found_obj = true;
629+
} else if (!strncmp((const char *)sec, ".eh_frame", 8)) {
630+
info.dwarf_section = begin;
631+
info.dwarf_section_length = u32(sec + 8);
632+
found_hdr = true;
633+
}
634+
if (found_obj && found_hdr)
635+
return true;
636+
}
637+
_LIBUNWIND_TRACE_UNWINDING("findUnwindSections: no .eh_frame section in the "
638+
"image at %p (%d sections)", (void *)base,
639+
(int)nsec);
640+
return false;
641+
}
642+
#else
643+
// ─── openkal ─── END
560644
HMODULE mods[1024];
561645
HANDLE process = GetCurrentProcess();
562646
DWORD needed;
@@ -596,6 +680,9 @@ inline bool LocalAddressSpace::findUnwindSections(
596680
}
597681
}
598682
return false;
683+
// ─── openkal ─── BEGIN
684+
#endif // OPENKAL
685+
// ─── openkal ─── END
599686
#elif defined(_LIBUNWIND_SUPPORT_SEH_UNWIND) && defined(_WIN32)
600687
// Don't even bother, since Windows has functions that do all this stuff
601688
// for us.

llvm/libunwind/src/RWMutex.hpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,23 @@
1313
#ifndef __RWMUTEX_HPP__
1414
#define __RWMUTEX_HPP__
1515

16-
#if defined(_WIN32)
16+
// ─── openkal ─── BEGIN
17+
//
18+
// The platform surface of this file is a read-write lock, and upstream picks it
19+
// by operating system: SRW locks on `_WIN32`, pthreads everywhere else. openkal
20+
// makes that question have one answer — `pthread_rwlock_*` is what is beneath on
21+
// every target, because musl is, and musl's rwlock is a futex, and the futex is
22+
// `kal_task_wait` / `kal_task_wake`. The same route `libcxx/src/atomic.cpp`
23+
// takes, and the same reason it takes it.
24+
//
25+
// ⚠️ THE INCLUDE IS OUTSIDE THE THREADS CHECK, WHICH IS WHY THIS IS A PATCH AND
26+
// NOT A FLAG. Upstream reaches `<windows.h>` on `_WIN32` BEFORE asking whether
27+
// this build has threads at all — so `_LIBUNWIND_HAS_NO_THREADS`, which would
28+
// otherwise make this file need nothing, does not prevent the include.
29+
#if defined(_WIN32) && !defined(OPENKAL)
1730
#include <windows.h>
1831
#elif !defined(_LIBUNWIND_HAS_NO_THREADS)
32+
// ─── openkal ─── END
1933
#include <pthread.h>
2034
#if defined(__ELF__) && defined(_LIBUNWIND_LINK_PTHREAD_LIB)
2135
#pragma comment(lib, "pthread")
@@ -34,7 +48,13 @@ class _LIBUNWIND_HIDDEN RWMutex {
3448
bool unlock() { return true; }
3549
};
3650

37-
#elif defined(_WIN32)
51+
// ─── openkal ─── BEGIN
52+
// ⚠️ THE SECOND OF TWO. The same fact — "this is PE, so use SRW locks" — is
53+
// stated twice in this file, once to pick the include and once to pick the
54+
// class. Withdrawing only the first leaves the class referring to `SRWLOCK`
55+
// with nothing declaring it.
56+
#elif defined(_WIN32) && !defined(OPENKAL)
57+
// ─── openkal ─── END
3858

3959
class _LIBUNWIND_HIDDEN RWMutex {
4060
public:

0 commit comments

Comments
 (0)