feat: getrandom through the interface layer, and getentropy where a consumer looks for it - #6
Closed
Sunrisepeak wants to merge 2 commits into
Closed
feat: getrandom through the interface layer, and getentropy where a consumer looks for it#6Sunrisepeak wants to merge 2 commits into
Sunrisepeak wants to merge 2 commits into
Conversation
…onsumer looks for it musl 自己的 `src/linux/getrandom.c` 直接发 `SYS_getrandom`。在 Linux 内核 底下时这是对的,在这里是错的:**这个 port 存在的理由就是让每一次请求 经 openkal 到达环境。** dispatch 里加一个 case,转给 `kal_random_fill` —— 与已经在那里的 69 个 系统调用同一条路。⚠️ flags 被忽略:`GRND_NONBLOCK` 要的是短读,而 `kal_random_fill` 没有 部分成功可报。一个会阻塞的环境在 `kal_random_props` 里说这件事。 ──⚠️ 并且 `getentropy` 的声明位置,glibc 与 musl 不同 ──────── glibc <sys/random.h> 声明 getrandom 与 getentropy musl <sys/random.h> 只声明 getrandom;getentropy 在 <unistd.h> 而 libc++ 的 GETENTROPY 分支只 include 前者: random.cpp:52:14: error: use of undeclared identifier 'getentropy' ⭐ 这正是 `port/include/` overlay 存在的问题类型 —— 消费者问的是 「这是哪个操作系统」并假定那个系统的 C 库,而这里的 C 库是 musl。 `port/include/sys/random.h` 用 `#include_next` 取回 musl 那份, 再补上那一行声明。⚠️ **只加声明,别的什么都不加。** 定义仍是 musl 的 `src/misc/getentropy.c`, 未经修改;本文件纠正的是消费者去哪里找这个名字。两处都声明正是 glibc 的做法, 也是消费者所针对的。 实测:`getentropy` 返回 0,两次调用字节不同 —— 整条链 `std::random_device → getentropy → getrandom → kal_random_fill → 后端` 全程走接口层。
Sunrisepeak
added a commit
to mcpplibs/openkal-llvm-runtime
that referenced
this pull request
Aug 24, 2026
使用者报 `_LIBCPP_HAS_RANDOM_DEVICE 0` 让 5 个 TU 编不过,本地改成 1 即修好。⚠️ 那个 0 不是保守设置,是当时事实的准确记录 —— 改成 1 只让编译期通过, 链接会缺符号。现在 openkal 有了随机源接口,这四层可以逐一拆掉。 **① 宏改为 1** —— 只在 `generic`;`freestanding` 保持 0,因为裸机后端 只有板子有源时才提供 `openkal.random`,而 6.1 条在链接期报告缺席。 **② `random.cpp` 曾被 sources 显式排除**,与那个宏配对。排除删掉。 **③⚠️ 默认后端在这里走不通,而它不会报错。** libc++ 对不认识的目标 落到 `_LIBCPP_USING_DEV_RANDOM`,那条要 `open("/dev/urandom")` —— 而能力型文件系统刻意不发绝对路径。必须在 `__config_site` 里**显式**选 `_LIBCPP_USING_GETENTROPY`:它不要描述符也不要路径。 **④ 声明找不到** —— musl 把 `getentropy` 放在 `<unistd.h>`,glibc 放在 `<sys/random.h>`,而 libc++ 只 include 后者。修在 openkal-musl 的 overlay (见 mcpplibs/openkal-musl#6)。 ⭐ 第三层最要紧:**那条默认路径在 openkal 上走不通,而它不报错, 只会在运行期打不开设备。** 实测,完整链路全程走接口层: std::random_device → getentropy → getrandom → kal_random_fill → 后端 x86_64-linux random_device: 3415089597 356442272 differ = true x86_64-windows random_device: 1945321362 2880234856 differ = true (wine) `entropy() = 0` 是 libc++ GETENTROPY 后端的既定行为,不是缺陷。
规范新增 `openkal.random`,版本升到 0.7.0。CI 的版本同步门要求实现与规范 同步声明 —— 它的诊断说得很准:「Nothing is wrong with either; they are not in step.」
Sunrisepeak
added a commit
to mcpplibs/openkal-llvm-runtime
that referenced
this pull request
Aug 25, 2026
…system one (#5) * fix: the x87 routines are an architecture property, not an operating-system one `--target aarch64-linux-musl` 编不过: truncxfhf2.c:13:36: error: unknown type name 'xf_float'; did you mean 'tf_float'? `*xf*.c` 与 `*xc3.c` 是 x87 80 位 `long double` 的例程。本清单里排除它们的 条件有两处,`cfg(os = "macos")` 与 `cfg(os = "none")` —— **都按操作系统分, 而这是架构的性质**。于是 aarch64-linux 落进 `os = "linux"` 那一支, 去编一个只有 x86 才有的类型。 ⭐ **两处此前都是对的,只是排错了轴。** `os = "macos"` 与 `os = "none"` 今天恰好都蕴含「非 x87 架构」,所以那条排除看起来像 OS 属性。它不是。⚠️ 并且 linux 段**不排除**它们也是对的,注释里记着理由:x86 上 `long double` 真是 x87 80 位,`-lgcc` 从链接行拿掉之后 ld.lld: error: undefined symbol: __mulxc3 —— libc++ `<complex>` 里的复数乘法真的会调它。所以这不是「多编了没用的 文件」,两个方向都会坏。 新增一段按架构分: [target.'cfg(all(os = "linux", not(arch = "x86_64")))'.build] sources = ["!…/*xf*.c", "!…/*xc3.c"] 按事实真正所在的那条轴来分,是让第二个架构可用而不必再抄一份列表的做法。 实测:该错误消失,构建推进到下一处(BMI 目标特性不匹配,另案)。 报告 mcpp-community/mcpp#492 (comment)。 * feat(aarch64): supply the 125 outline-atomics helpers, because this package is that compiler-rt `--target aarch64-linux-musl` 链接失败: ld.lld: error: undefined symbol: __aarch64_swp4_acq ld.lld: error: undefined symbol: __aarch64_cas8_acq_rel ⭐ **`--rtlib=compiler-rt` 让 clang 在 aarch64 上开启 `+outline-atomics`, 而它是对的** —— 那些 `__aarch64_*` 辅助函数本来就住在 compiler-rt 里, 只是本包没产出它们。特性被开启而无人实现,于是缺符号。⚠️ 引用来自 `openkal-linux/src/memory.o` 与 `openkal-musl/port/src/okm_fd.o` —— 两个对这件事一无所知、只是用了原子操作的包。**缺的是这份运行时该有的 东西**,所以修在这里,而不是让引擎去关掉那个特性。 ── ⭐ 把宏从命令行移进文件,而不是复制 125 份实现 ──────── upstream 用 CMake 把 `aarch64/lse.S` 编 125 遍,每遍给不同的 `-DL_<pat> -DSIZE=<n> -DMODEL=<m>`(6 模式 × 5 尺寸 × 5 模型, 非 cas 的 16 字节档不存在)。`sources` 是 glob,传不了 per-file 定义。 于是每个组合成为一个**只声明宏、再 include 共享正文**的小文件: #define L_cas #define SIZE 1 #define MODEL 1 #include "../../llvm/compiler-rt/lib/builtins/assembly.h" #include "../../llvm/compiler-rt/lib/builtins/aarch64/lse.S" 正文是 upstream 的、未经修改、留在原处 —— `git diff` 对着一份新 checkout 仍然为空。 ──⚠️ 途中两处「以为做完了其实没有」 ────────────────── **① `#include "assembly.h"` 解析不到。** upstream 靠 `INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}"` 供给;生成的文件在 别的目录,汇编器于是把 `HIDDEN(...)` 读成指令: error: unrecognized instruction mnemonic 解法是让生成文件**自己按相对自身的路径 include 那个头** —— 不需要任何 flag,而 flag 正是「任何再包含这个目录的人都得重复一遍」的那种东西。 **② `__aarch64_have_lse_atomics` 未定义。** 125 个辅助函数每个都读它 —— 运行时决定走 LSE 指令还是 load/store-exclusive 循环。它在 `cpu_model/aarch64.c`,而 `[build]` 段的 glob 是 `builtins/*.c`, **不含子目录**,所以这个文件从未被编过。 ── 实测 ──────────────────────────────────────────── 已定义的 __aarch64_* 符号 10 未定义 0 产物中的 LSE 指令 8 处 ← 特性真的在工作 file ELF 64-bit LSB executable, ARM aarch64, statically linked ⭐ 这是**真正支持**,不是关掉特性绕过去。mcpp 引擎零改动。 来源:mcpp-community/mcpp#492 (comment)。 * fix(aarch64): disable FMV — half that file cannot compile on a macOS host `cpu_model/aarch64.c` 的后半是函数多版本(FMV),按宿主分支 include 一个 `.inc`。Apple 那支拉系统头: aarch64/fmv/apple.inc:1:10: fatal error: 'TargetConditionals.h' file not found 而本包的 `include_dirs` 刻意不含任何来自机器的路径(见该段的 ⭐⭐ NOTHING FROM THE MACHINE)。⚠️ 本机 Linux 编得过,CI 的 macOS 那格才炸 —— 典型的「一台宿主看不见」的形状。 ⭐ 本包**不需要** FMV:要的只是 `__aarch64_have_lse_atomics`,它定义在 `#if !defined(DISABLE_AARCH64_FMV)` **之外**。upstream 自己带这个开关 (`COMPILER_RT_DISABLE_AARCH64_FMV`),所以这是走它给的门,不是绕过。 实测关掉后 aarch64 仍产出 ARM aarch64 静态 ELF,10 个 __aarch64_* 符号 已定义、0 个未定义。 * feat: std::random_device works, and it took four layers to make it so 使用者报 `_LIBCPP_HAS_RANDOM_DEVICE 0` 让 5 个 TU 编不过,本地改成 1 即修好。⚠️ 那个 0 不是保守设置,是当时事实的准确记录 —— 改成 1 只让编译期通过, 链接会缺符号。现在 openkal 有了随机源接口,这四层可以逐一拆掉。 **① 宏改为 1** —— 只在 `generic`;`freestanding` 保持 0,因为裸机后端 只有板子有源时才提供 `openkal.random`,而 6.1 条在链接期报告缺席。 **② `random.cpp` 曾被 sources 显式排除**,与那个宏配对。排除删掉。 **③⚠️ 默认后端在这里走不通,而它不会报错。** libc++ 对不认识的目标 落到 `_LIBCPP_USING_DEV_RANDOM`,那条要 `open("/dev/urandom")` —— 而能力型文件系统刻意不发绝对路径。必须在 `__config_site` 里**显式**选 `_LIBCPP_USING_GETENTROPY`:它不要描述符也不要路径。 **④ 声明找不到** —— musl 把 `getentropy` 放在 `<unistd.h>`,glibc 放在 `<sys/random.h>`,而 libc++ 只 include 后者。修在 openkal-musl 的 overlay (见 mcpplibs/openkal-musl#6)。 ⭐ 第三层最要紧:**那条默认路径在 openkal 上走不通,而它不报错, 只会在运行期打不开设备。** 实测,完整链路全程走接口层: std::random_device → getentropy → getrandom → kal_random_fill → 后端 x86_64-linux random_device: 3415089597 356442272 differ = true x86_64-windows random_device: 1945321362 2880234856 differ = true (wine) `entropy() = 0` 是 libc++ GETENTROPY 后端的既定行为,不是缺陷。 * release: 0.1.3, on openkal-musl 0.3.4 `std::random_device` needs `getentropy` declared where libc++ looks for it, which is `<sys/random.h>` — glibc's layout, and the one libc++ is written against. musl declares it in `<unistd.h>`, and openkal-musl 0.3.4 adds an overlay header that declares it in both places, as glibc does. Below that, `SYS_getrandom` is forwarded to `kal_random_fill` rather than issued as a system call, so the entropy comes through the interface layer on every system openkal has an implementation for. std::random_device → getentropy → getrandom → syscall_cp(SYS_getrandom) → port dispatch → kal_random_fill → backend 0.1.2 is the version in the index and the version this branch carried, and the content behind that number has changed: this branch also supplies the 125 outline-atomics helpers for aarch64 and stops excluding the x87 routines by operating system. * docs: the generated files said 130 while their own arithmetic said 125 Every one of the 125 files opened with "One of the 130 instantiations", and the same comment then described a rule that yields 125. Upstream's CMake is the arbiter and agrees with the arithmetic, not the number: foreach(pat cas swp ldadd ldclr ldeor ldset) foreach(size 1 2 4 8 16) foreach(model 1 2 3 4 5) if(pat STREQUAL "cas" OR NOT size STREQUAL "16") `cas` at five sizes and five further patterns at four sizes, times five orderings: 25 + 100. The directory holds 125 files, which is what a reader would have counted if the sentence had not told them otherwise. * fix(freestanding): random.cpp must not be compiled where the switch is off Removing the `!llvm/libcxx/src/random.cpp` exclusion was right for the hosted configuration, which turned `_LIBCPP_HAS_RANDOM_DEVICE` on. The freestanding configuration keeps it at 0 — a bare-metal backend provides `openkal.random` only if its board has a source, and clause 6.1 reports that absence at link time rather than at compile time — and the same removal reached it. With the switch off, `<random>` does not declare the class while `src/random.cpp` defines its members unconditionally; that file carries no guard of its own, unlike the filesystem sources beside it: llvm/libcxx/src/random.cpp:68:1: error: use of undeclared identifier 'random_device'⚠️ One exclusion, two decisions. The hosted block and the freestanding block disagree about the switch, so they cannot share the removal — and the comment in the hosted block already stated the freestanding position without acting on it. * deps: openkal-musl 0.3.5 0.3.4's syscall dispatcher referenced `kal_random_fill` strongly, which made an optional interface mandatory: this package's freestanding target links a program over openkal-opensbi, which does not provide `openkal.random`, and the link failed on a symbol nothing in the program asked for. ld.lld: error: undefined symbol: kal_random_fill * docs: the freestanding switch refuses at compile time, not at link time The note said clause 6.1 would report the absence at link time. It does not: with `_LIBCPP_HAS_RANDOM_DEVICE` at 0, `<random>` does not declare the class, so a bare-metal program naming `std::random_device` is refused where it is written. __random/random_device.h:24: #if _LIBCPP_HAS_RANDOM_DEVICE __random/random_device.h:26: class random_device { That is the better of the two diagnoses and it is the one that happens; what was wrong was the account of it. The reason mattered because the same sentence was the argument for keeping the switch off, and an argument resting on a mechanism that does not apply is one nobody can check. Also records what the switch cannot express: a board with a hardware source could have a backend that provides `openkal.random`, and this answer would still be 0. The configuration is generated once, before any graph is resolved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
musl 的
src/linux/getrandom.c直接发SYS_getrandom——在 Linux 内核底下对,在这里错:这个 port 的理由就是让每次请求经 openkal 到达环境。dispatch 加一个 case 转给
kal_random_fill,与已在那里的 69 个系统调用同路。而 libc++ 的 GETENTROPY 分支只 include 前者:
error: use of undeclared identifier 'getentropy'。⭐ 这正是⚠️ 只加声明,定义仍是 musl 的、未改。
port/include/overlay 的问题类型——消费者问「这是哪个操作系统」并假定那个系统的 C 库,而这里的 C 库是 musl。用#include_next取回 musl 那份再补一行声明。实测:整条链全程走接口层,两次调用字节不同。依赖 mcpplibs/openkal#8。