Feat/gdb smoke x86 64 native#1330
Conversation
… support 补齐 x86_64 ptrace 主干功能: - 新增 `X8664UserRegs` 结构体 (repr(C)),对应 Linux `user_regs_struct`,含 r15..rsp/ss/fs_base/gs_base 全部 27 个字段 - 实现 `From<UserContext> for X8664UserRegs` 和 `write_to()` - 补齐 x86_64 上之前缺失的 ptrace opcode: GETREGS / SETREGS / GETREGSET(NT_PRSTATUS) / SETREGSET(NT_PRSTATUS) / GETSIGINFO / SETSIGINFO - 将 `ptrace_getregset_prstatus` 中 `regs` 局部变量从内部 block 提升到 函数级作用域,修复 reg_bytes slice 的 use-after-free bug(regs 出 block 后被栈复用覆盖,导致用户态读到随机值,表现为 RSP=0x1) - 新增 `ptrace_setup_singlestep` for x86_64:设置 RFLAGS 的 TF (bit 8) 触发 CPU 单步执行 - 为 x86_64 添加 singlestep setup 调用(之前仅 riscv64) - 新增 `ExceptionKind::Debug` 处理分支:命中 traced task 的 #DB 异常时,清除 TF 并调用 ptrace_stop_current(SIGTRAP) - Intel SDM 规定 CPU 在交付 TF 诱导的 #DB 时会清除 pushed RFLAGS 中的 TF,但 QEMU 不完全遵守,故显式清除防止 resume 后再次单步 | 测试 | 验证内容 | |------|----------| | test-ptrace-x86-regs | TRACEME -> GETREGS/GETREGSET/SETREGS/SETREGSET 闭环 | | test-ptrace-exec-stop | TRACEME + execve -> SIGTRAP + DETACH | | test-ptrace-x86-breakpoint | 双测试:software int3 最小闭环 + SINGLESTEP 基础验证 | | test-ptrace-x86-singlestep | PTRACE_SINGLESTEP 执行一条指令后以 SIGTRAP stop | | test-ptrace-x86-breakpoint-reinsert | gdb 风格断点恢复:rewind RIP -> 恢复原字节 -> SINGLESTEP -> 重新插入断点 -> 再次命中 | | test-gdb-native-batch | gdb -q -batch 端到端:break native_marker / run / bt / info registers / continue | 所有 6 个 x86_64 ptrace case 全部通过。
…docs - apps/starry/gdb: gdb --version smoke test for x86_64 QEMU (qemu-x86_64.toml, build-x86_64-unknown-none.toml, prebuild.sh) - docs: update mount-umount2 Linux compat documentation with shared/private/slave/unbindable propagation, bind subdirectory, MS_MOVE ELOOP, MS_REMOUNT|MS_BIND|MS_RDONLY semantics
…64")] ExceptionKind::Debug and uctx.rflags only exist on x86_64, but the Debug exception handler in user.rs had no cfg guard, leaking x86_64 single-step logic into all architecture builds. Wrap the entire block in #[cfg(target_arch = "x86_64")]. Fixes CI failures on loongarch64/aarch64/riscv64.
The prebuild script used 'docker run alpine:edge apk add gdb' which requires the Docker daemon that is not available inside the CI container. Switch to qemu-x86_64-static + native apk, consistent with gdb-smoke/prebuild.sh.
…6_64 gdb install qemu-x86_64-static hangs when emulating x86_64 binaries on an x86_64 host during network-heavy operations like 'apk' package downloads. Use the musl dynamic linker (ld-musl-x86_64.so.1) from the staging rootfs to run Alpine apk natively without any emulation layer.
Replace docker-run-based gdb install with native musl ld execution of Alpine apk, fixing DNS resolution for the staging root. Add missing gdb/Python runtime assets to overlay: - /usr/share/gdb/ (gdb Python modules, syscalls, system-gdbinit) - /usr/lib/python3.12/ (Python stdlib) - /usr/lib/python312.zip - libpython3.12.so* - /usr/bin/python3
The build config only had the 'qemu' feature which does not automatically enable virtio drivers. Without ax-driver/virtio-blk, the kernel cannot detect the root block device, causing: 'failed to determine root device from available block devices' Align with gdb-smoke's build config by adding the required ax-driver/virtio-blk and ax-driver/virtio-net features.
Align gdb app build config with gdb-smoke and test-suit configs.
CMake install(PROGRAMS ...) preserves symlinks from the staging rootfs, which causes inject_overlay to fail with: 'unsupported overlay entry ... only regular files and directories are supported' When a symlink is encountered during overlay traversal, use debugfs symlink command to create the symbolic link in the target ext4 image instead of bailing out.
…SETFPREGS/NT_FPREGSET)
The debugfs symlink command expects "symlink <link_path> <target>" matching mke2fs convention. Also harden the x86_64 ptrace test with canary-fork cleanup detection and kernel fault regexes.
When vaddr < file_vaddr_base (page-aligned-down start in unaligned mappings), the saturating_sub returned 0 instead of correctly subtracting the gap from file_start. This caused wrong file data to be read after mprotect-induced VMA splits. Fixes bug-unaligned-cow-split test failure on loongarch64.
…ecve diagnostics - map_elf(): scan PT_TLS segments and extend last PT_LOAD file_end so the COW backend can serve TLS init-image page faults for the dynamic linker. Without this, ldso sees zeroed TLS data on riscv64, leading to pc=0 crashes after execve. - execve: add diagnostic logging for entry/sp/tp/ldso presence to help debug future user-mode startup failures.
…unds scan
The auxv constructed in ElfLoader::load() was missing the AT_NULL
(type=0) terminator that the musl dynamic linker uses to stop scanning.
Without it, ld-musl reads past the auxv array into environment string
data on the stack, interpreting arbitrary bytes as auxv entries.
The second exec in init.sh ("exec /bin/sh -l -i") inherits env vars
from the first shell, reshaping the stack so that the out-of-bounds
scan hits garbage aliasing AT_PHDR or AT_ENTRY, producing pc=0 SIGSEGV
with exit code 139. The first exec succeeds only by coincidence — its
empty envp produces a less harmful stack layout.
Fix: push AuxEntry::new(AuxType::NULL, 0) after AT_HWCAP to properly
terminate the auxv.
OrangePi-5-Plus and SG2002 board tests were timing out after 300-600s because SIGSEGV crashes (busybox mesg, busybox shell) were not caught by fail_regex, so the runner waited for the full timeout instead of failing fast. Add three patterns to all board test TOMLs: - '(?i)segmentation fault' - '(?i)SIGSEGV' - 'exit with code: 139' This ensures that any userspace SIGSEGV during boot/login is detected immediately instead of being hidden behind a timeout.
…tics - ElfLoader::load(): add AuxType::NULL terminator to the auxv Vec - Add info! diagnostic for entry/auxv_count/ldso/last_auxv_type - execve: upgrade to info! with image name for crash correlation - map_elf(): downgrade PT_TLS log to debug!
…scv64 On real hardware with non-coherent L1 I/D caches (T-Head C906 on SG2002), a recycled physical frame from a prior exec may still hold stale instruction-cache lines. New code bytes written via D-cache stores by the COW backend are invisible to the I-cache unless fence.i is executed, causing the CPU to fetch garbage instructions and jump to pc=0. Add fence.i (flush_icache_all) in handle_page_fault after populating any page with EXECUTE permission. QEMU has no real caches so this is a nop in simulation. Also replace the stale 'TDOO: flush the I-cache' comment in loader.rs with a note that coherence is now maintained at fault time.
ptrace_getfpregs/ptrace_setfpregs use the generic ArchFpRegs path for the non-x86 architectures, but the supported arm was gated on any(riscv64, loongarch64) (missing aarch64) while the Unsupported fallback was gated on not(any(riscv64, x86_64)). On loongarch64 both arms matched, causing E0428 (duplicate definition); on aarch64 the function fell through to the Unsupported stub instead of the real ArchFpRegs path. Widen the supported arm to any(riscv64, aarch64, loongarch64) and the fallback to not(any(riscv64, aarch64, loongarch64, x86_64)), matching get/setregs.
During an earlier conflict resolution, pseudofs/proc.rs was reverted to a pre-refactor version, silently dropping upstream features: /proc/<pid>/mem (ProcMemFile + read_at/write_at/check_access), /proc/<pid>/status memory stats (sample_mem_stats, TaskStatusBase/TaskStatusFields) and the namespace directory (NsDir), plus their tests. Restore the current upstream/dev proc.rs and re-apply the only two genuine branch-local tweaks on top: the extended loongarch /proc/cpuinfo Feat flags, and /proc/<pid>/maps full-width addresses with anonymous-mapping file_info tolerance.
An earlier divergence replaced the two-pass overlay debugfs injection with a single-pass variant, dropping two upstream behaviours: deferring symlink creation until after their targets are written (debugfs validates the target), and converting relative symlink targets to absolute guest paths. Restore the upstream/dev implementation (which already uses link-path-first symlink args).
format_statm and format_status_vm_lines had been marked #[cfg(test)] back when the reverted proc.rs no longer called them (to avoid dead_code under -D warnings). The restored proc.rs uses both in the real build (/proc/<pid>/statm and /proc/<pid>/status), so the test-only gating broke non-x86 builds with E0599. Restore upstream/dev stats.rs so the methods are available in all builds.
A 172KB GitHub page snapshot (Feat_x86 64 ptrace clean ... rcore-os_tgoskits@f4d00dd.html) was swept into the branch by a stray 'git add .'. It is not source/test asset and makes 'git diff --check' fail on trailing whitespace/EOF blank lines. Remove it and gitignore these page snapshots so they cannot be re-committed.
starry app qemu injects the rootfs image path as STARRY_ROOTFS, not
STARRY_BASE_ROOTFS, so the gdb prebuild failed require_env and the
GDB_SMOKE_PASSED qemu path never ran. Match the ffmpeg/pip/mosquitto apps:
read ${STARRY_ROOTFS:-${STARRY_BASE_ROOTFS:-}} and require STARRY_ROOTFS.
…gs explicit-TID backend - Add ArchUserRegs alias for x86_64 - Make write_to return AxResult<()> for all archs - Expand generic read/write backends to cover x86_64 - Remove parallel x86_64 helper functions - Unify getregs/setregs into single generic bodies - Remove inline arch dispatch from getregset/setregset_prstatus - Update PEEKUSER/POKEUSER user-area to generic backend - Remove redundant selected-stop wrappers from detach_live_tracees_of
The gdb app x86_64 build config pinned the legacy static x86 platform (ax-hal/x86-pc, ax-driver/plat-static, the qemu feature, plat_dyn=false). x86_64 Starry runs on the dynamic platform path, which registers no static platform package, so 'cargo xtask starry app qemu -t gdb --arch x86_64' failed at build-config with 'no default platform package is registered for arch x86_64' and the GDB_SMOKE_PASSED path was unreachable. Drop the static deps and match the other Starry x86_64 app configs (git/top): keep only the virtio driver features on the dynamic platform. Verified end-to-end in the container: boots to a shell, gdb 16.3 runs, GDB_SMOKE_PASSED.
…ner (rcore-os#1315) Signed-off-by: 林晨 (Leo Cheng) <chengkelfan@qq.com>
x86_64 PTRACE_PEEKUSER/POKEUSER on the debug-register area used X86_64_USER_DEBUGREG_OFFSET = 912, but u_debugreg[] sits at offset 848 in the x86_64 `struct user` (regs 216 + u_fpvalid/pad 8 + i387 512 + tsize/ dsize/ssize 24 + start_code/start_stack 16 + signal 8 + reserved/pad 8 + u_ar0 8 + u_fpstate 8 + magic 8 + comm 32 = 848). gdbserver probes the hardware debug registers (DR0–DR7) via PEEKUSER at this offset during startup; with the wrong offset it read a bogus location and stalled before printing "Listening on port 1234", so the x86_64 gdbserver smoke hung. The native single-process GDB smoke does not touch debug registers, which is why only the gdbserver path was affected. Fix the offset to 848. Verified end-to-end in the container: the x86_64 gdbserver smoke now reaches GDBSERVER_SMOKE_DONE.
参照现有 riscv64/aarch64/loongarch64 实现,为 gdb-smoke 增加 x86_64 的 原生 GDB 冒烟与单进程 gdbserver 冒烟移植: - 新增 build-x86_64-unknown-none.toml 与默认 qemu-x86_64.toml(native 批量冒烟,成功标志 GDB_NATIVE_SMOKE_DONE); - 补齐 gdbserver 全套:qemu-x86_64-gdbserver.toml(默认 gdbserver 冒烟, GDBSERVER_SMOKE_DONE)、gdbserver-host.toml、gdbserver-manual.toml,以及 host-remote-x86_64.gdb / host-manual-x86_64.gdb(set architecture i386:x86-64); - prebuild.sh 的 find_qemu_runner 增加 x86_64 分支(qemu-x86_64 + x86_64-linux-musl); - README 补充 x86_64 native 与 gdbserver 用法。 gdbserver 路径依赖同分支的 x86_64 u_debugreg 偏移修复才能跑通。已在容器内 验证:native 冒烟 GDB_NATIVE_SMOKE_DONE、gdbserver 冒烟 GDBSERVER_SMOKE_DONE 均通过(断点/backtrace/continue/远程连接/正常退出全部正确)。
There was a problem hiding this comment.
审查总结
本 PR 为 gdb-smoke 应用添加 x86_64 支持,并修复 X86_64_USER_DEBUGREG_OFFSET 常量值。
变更内容
-
gdb-smoke x86_64 支持(8 个文件新增,2 个文件修改):
- 新增
qemu-x86_64.toml、qemu-x86_64-gdbserver.toml、qemu-x86_64-gdbserver-manual.toml、qemu-x86_64-gdbserver-host.toml四个 QEMU 配置 - 新增
build-x86_64-unknown-none.toml构建配置 - 新增
host-manual-x86_64.gdb和host-remote-x86_64.gdbGDB 脚本 - 更新
prebuild.sh:添加 x86_64 架构支持和find_gcc_install_dir()用于定位 GCC crt 对象 - 更新 README 添加 x86_64 使用说明
- 新增
-
ptrace 常量修复(1 行变更):
X86_64_USER_DEBUGREG_OFFSET从 912 改为 848
代码审查
- 所有新增 QEMU 配置和 GDB 脚本均遵循现有 riscv64/aarch64/loongarch64 的模式,结构一致。
prebuild.sh中find_gcc_install_dir()逻辑清晰,查找crtbeginT.o所在目录用于 x86_64 musl 链接。X86_64_USER_DEBUGREG_OFFSET修改是正确的:在 Starry 自定义的user area布局中,u_comm结束于816 + 32 = 848,debugreg 应从 848 开始。旧值 912 与布局不一致。- 注意:此偏移量(848)与 Linux 标准
struct user中u_debugreg的偏移量(344)不同,这是 Starry 在 user area 中内嵌完整 FP 状态(512 字节)的设计决策,非本 PR 引入。
CI 状态
Detect changed paths:✅ 成功Cancel stale CI runs:✅ 成功Run sync-lint / run_container:✅ 成功Check formatting / run_host:进行中(本地cargo fmt --check已通过)- 其他 container/publish 任务:跳过(符合 host/container 矩阵分流预期)
CI 无失败项。sync-lint 已通过,格式检查进行中但本地验证通过。
本地验证
cargo fmt --check:✅ 通过
重复/重叠分析
- 检查了 open PR 列表,无其他 PR 涉及 gdb-smoke x86_64 支持。
- PR #1329 修改
components/axcpu/src/x86_64/context.rs(FxsaveArea 的 XSAVE 支持),与本 PR 无文件冲突。
测试覆盖
PR 仅添加 app 配置和一个常量修复,未新增 test-suit 用例。根据 commit 历史,作者已在前序提交中验证了 6 个 x86_64 ptrace 测试用例全部通过。app 层面的 QEMU 运行验证需要 cargo xtask starry app qemu -t gdb-smoke --arch x86_64,由于环境限制无法本地运行,但配置与现有架构一致。
结论
PR 代码清晰,遵循现有模式,CI 无阻断性失败。建议 APPROVE。
Powered by mimo-v2.5-pro
There was a problem hiding this comment.
审查总结
本 PR 为 gdb-smoke 应用添加 x86_64 native 支持,并修复 X86_64_USER_DEBUGREG_OFFSET 常量值。
变更内容
-
gdb-smoke x86_64 支持(8 个文件新增,2 个文件修改):
- 新增 4 个 QEMU 配置:
qemu-x86_64.toml、qemu-x86_64-gdbserver.toml、qemu-x86_64-gdbserver-manual.toml、qemu-x86_64-gdbserver-host.toml - 新增
build-x86_64-unknown-none.toml构建配置 - 新增
host-manual-x86_64.gdb和host-remote-x86_64.gdbGDB 脚本 - 更新
prebuild.sh:添加 x86_64 架构支持和find_gcc_install_dir()用于定位 GCC crt 对象 - 更新 README 添加 x86_64 使用说明
- 新增 4 个 QEMU 配置:
-
ptrace 常量修复(1 行变更):
X86_64_USER_DEBUGREG_OFFSET从 912 改为 848
代码审查
- 所有新增 QEMU 配置遵循现有 riscv64/aarch64/loongarch64 的模式,结构一致。x86_64 使用
cpu max、to_bin = false,合理。 prebuild.sh中find_gcc_install_dir()逻辑清晰,查找crtbeginT.o所在目录用于 x86_64 musl 链接。-B/-L标志对所有架构安全(冗余但无害)。X86_64_USER_DEBUGREG_OFFSET修复正确:在 Starry 自定义的 user area 布局中,X86_64_USER_COMM_OFFSET = 816,X86_64_USER_COMM_SIZE = 32,因此 debugreg 应从 816 + 32 = 848 开始。旧值 912 = 848 + 64 实际上是 debugreg 数组的末尾而非起始位置,这是一个确认的 bug。- GDB 脚本设置
architecture i386:x86-64,正确。 - 注意:此偏移量(848)与 Linux 标准
struct user中u_debugreg的偏移量(344)不同,这是 Starry 在 user area 中内嵌完整 FP 状态(512 字节)的设计决策,非本 PR 引入。
CI 状态
Check formatting / run_host:✅ 成功Run sync-lint / run_container:✅ 成功Detect changed paths:✅ 成功Cancel stale CI runs:✅ 成功- 多项 QEMU 测试已通过(arceos x86_64/loongarch64/riscv64, axvisor aarch64/riscv64/loongarch64)
- 16 项检查仍在运行中,无任何失败
重复/重叠分析
- PR #1329 修改
components/axcpu/src/x86_64/context.rs(XSAVE 支持),与本 PR 无文件冲突。 - 未发现其他 PR 涉及 gdb-smoke x86_64 支持或相同 ptrace 修复。
测试覆盖
PR 主要是 app 配置和一个常量修复。debugreg 偏移修复由 gdb-smoke x86_64 native 测试间接验证(完整的 ptrace 调试流程)。App 层面的 QEMU 运行验证需要 cargo xtask starry app qemu -t gdb-smoke --arch x86_64,CI 已有相关 QEMU 测试正在运行。
结论
PR 代码清晰,遵循现有模式,debugreg 偏移修正正确且关键,CI 无阻断性失败。建议 APPROVE。
Powered by mimo-v2.5-pro
ZR233
left a comment
There was a problem hiding this comment.
本轮复查的是当前 head d035b375f994b74a5b396de0ef38ba36b8610663。
这个 PR 的实际变更面比较集中:为 apps/starry/gdb-smoke 补齐 x86_64 native GDB 与单进程 gdbserver 的 QEMU 配置、host GDB 脚本和 prebuild 支持,同时把 x86_64 struct user 中 debug register 区域的 PTRACE_PEEKUSER/POKEUSER 偏移从 912 修正为 848。按当前代码里的 user-area 布局,X86_64_USER_COMM_OFFSET 为 816、长度 32,因此 debug register 起点是 848;旧值 912 实际越过了 8 个 debug register slot。这个修正也和 gdbserver 启动时探测 DR0-DR7 的行为相匹配。
测试覆盖方面,这里属于 app/QEMU workflow 变更,不能只看格式或普通 CI。我在隔离 worktree 中跑了文档新增的两个 x86_64 路径:
cargo xtask starry app qemu -t gdb-smoke --arch x86_64:通过,QEMU 内命中GDB_NATIVE_SMOKE_DONE,覆盖断点、backtrace、info proc mappings/files/auxv、寄存器读取、内存查看、stepi和正常退出。cargo xtask starry app qemu -t gdb-smoke --arch x86_64 --qemu-config qemu-x86_64-gdbserver.toml:通过,QEMU 内命中GDBSERVER_SMOKE_DONE,能看到 gdbserverListening on port 1234、host GDB 连接、断点命中、backtrace、continue 和 tracee 正常退出。
两次 prebuild 中 debugfs rdump 打印了若干 root-owned 文件 ownership preservation 警告,但命令最终成功完成 overlay 注入、内核构建和 QEMU 运行;这些警告没有影响本次 app workflow 的通过条件。
当前 head 的远端 CI 也已通过相关常规覆盖:Check formatting / run_host、Run clippy / run_host、Run sync-lint / run_container、Test starry x86_64 qemu / run_container 以及其它 ArceOS/Axvisor/Starry QEMU 和 self-hosted board 检查均为 pass,container/host 互斥矩阵中的 skipped 项属于预期分流。
重复和重叠检查:base 分支已有 riscv64/aarch64/loongarch64 的 gdb-smoke 路径,以及旧的 x86_64 debugreg 偏移 912;没有等价的 x86_64 gdb-smoke/gdbserver 配置。相关 open PR 中 #1314 也触及 x86_64 ptrace/GDB,但它是更广的后续语义收敛,包含 FP regset 共用、single-step 状态清理、统一 test-ptrace-gdb、以及 debug register 写入能力边界调整;与本 PR 的 x86_64 app 配置和 debugreg offset 修复属于部分重叠/后续整合关系,不构成本 PR 的重复实现。后续若 #1314 合入,需要按当前 base/本 PR 结果解决语义合并,但不阻塞本 PR 当前变更。
未发现阻塞问题。测试位置也符合 app-support 规则:gdb-smoke 是 operator/app workflow,位于 apps/starry/gdb-smoke;本 PR 没有把 app workflow 放入 test-suit/starryos,并且实际 QEMU app 命令已在当前 head 验证通过。
* feat(starry-kernel): x86_64 ptrace register r/w and PTRACE_SINGLESTEP support
补齐 x86_64 ptrace 主干功能:
- 新增 `X8664UserRegs` 结构体 (repr(C)),对应 Linux
`user_regs_struct`,含 r15..rsp/ss/fs_base/gs_base 全部 27 个字段
- 实现 `From<UserContext> for X8664UserRegs` 和 `write_to()`
- 补齐 x86_64 上之前缺失的 ptrace opcode:
GETREGS / SETREGS / GETREGSET(NT_PRSTATUS) / SETREGSET(NT_PRSTATUS) /
GETSIGINFO / SETSIGINFO
- 将 `ptrace_getregset_prstatus` 中 `regs` 局部变量从内部 block 提升到
函数级作用域,修复 reg_bytes slice 的 use-after-free bug(regs 出 block
后被栈复用覆盖,导致用户态读到随机值,表现为 RSP=0x1)
- 新增 `ptrace_setup_singlestep` for x86_64:设置 RFLAGS 的 TF (bit 8)
触发 CPU 单步执行
- 为 x86_64 添加 singlestep setup 调用(之前仅 riscv64)
- 新增 `ExceptionKind::Debug` 处理分支:命中 traced task 的 #DB
异常时,清除 TF 并调用 ptrace_stop_current(SIGTRAP)
- Intel SDM 规定 CPU 在交付 TF 诱导的 #DB 时会清除 pushed RFLAGS
中的 TF,但 QEMU 不完全遵守,故显式清除防止 resume 后再次单步
| 测试 | 验证内容 |
|------|----------|
| test-ptrace-x86-regs | TRACEME -> GETREGS/GETREGSET/SETREGS/SETREGSET 闭环 |
| test-ptrace-exec-stop | TRACEME + execve -> SIGTRAP + DETACH |
| test-ptrace-x86-breakpoint | 双测试:software int3 最小闭环 + SINGLESTEP 基础验证 |
| test-ptrace-x86-singlestep | PTRACE_SINGLESTEP 执行一条指令后以 SIGTRAP stop |
| test-ptrace-x86-breakpoint-reinsert | gdb 风格断点恢复:rewind RIP -> 恢复原字节 -> SINGLESTEP -> 重新插入断点 -> 再次命中 |
| test-gdb-native-batch | gdb -q -batch 端到端:break native_marker / run / bt / info registers / continue |
所有 6 个 x86_64 ptrace case 全部通过。
* feat(starry): add gdb smoke test app and update mount-umount2 compat docs
- apps/starry/gdb: gdb --version smoke test for x86_64 QEMU
(qemu-x86_64.toml, build-x86_64-unknown-none.toml, prebuild.sh)
- docs: update mount-umount2 Linux compat documentation with
shared/private/slave/unbindable propagation, bind subdirectory,
MS_MOVE ELOOP, MS_REMOUNT|MS_BIND|MS_RDONLY semantics
* fix(starry-kernel): gate #DB handler behind #[cfg(target_arch = "x86_64")]
ExceptionKind::Debug and uctx.rflags only exist on x86_64, but the
Debug exception handler in user.rs had no cfg guard, leaking x86_64
single-step logic into all architecture builds. Wrap the entire
block in #[cfg(target_arch = "x86_64")].
Fixes CI failures on loongarch64/aarch64/riscv64.
* test(starryos): extend gdb batch timeout
* test(starryos): isolate gdb apk install stage
* fix(starry-kernel): harden x86_64 ptrace reg writes
* fix(starryos): bundle gdb runtime for batch test
* fix(apps): replace docker-run gdb install with qemu-user + native apk
The prebuild script used 'docker run alpine:edge apk add gdb' which requires
the Docker daemon that is not available inside the CI container. Switch to
qemu-x86_64-static + native apk, consistent with gdb-smoke/prebuild.sh.
* fix(apps): use musl ld directly instead of qemu-user for same-arch x86_64 gdb install
qemu-x86_64-static hangs when emulating x86_64 binaries on an x86_64
host during network-heavy operations like 'apk' package downloads. Use
the musl dynamic linker (ld-musl-x86_64.so.1) from the staging rootfs
to run Alpine apk natively without any emulation layer.
* fix(apps): fix gdb app prebuild with musl ld and complete runtime assets
Replace docker-run-based gdb install with native musl ld execution
of Alpine apk, fixing DNS resolution for the staging root.
Add missing gdb/Python runtime assets to overlay:
- /usr/share/gdb/ (gdb Python modules, syscalls, system-gdbinit)
- /usr/lib/python3.12/ (Python stdlib)
- /usr/lib/python312.zip
- libpython3.12.so*
- /usr/bin/python3
* fix(apps): enable virtio-blk and virtio-net drivers for gdb app
The build config only had the 'qemu' feature which does not
automatically enable virtio drivers. Without ax-driver/virtio-blk,
the kernel cannot detect the root block device, causing:
'failed to determine root device from available block devices'
Align with gdb-smoke's build config by adding the required
ax-driver/virtio-blk and ax-driver/virtio-net features.
* fix(apps): add missing virtio-gpu, virtio-input, virtio-socket features
Align gdb app build config with gdb-smoke and test-suit configs.
* fix(axbuild): handle symlinks in overlay injection via debugfs
CMake install(PROGRAMS ...) preserves symlinks from the staging
rootfs, which causes inject_overlay to fail with:
'unsupported overlay entry ... only regular files and directories
are supported'
When a symlink is encountered during overlay traversal, use debugfs
symlink command to create the symbolic link in the target ext4 image
instead of bailing out.
* chore(ci): trigger re-run
* chore(ci): trigger re-run 2
* fix(starry-kernel): add x86_64 ptrace FP register support (GETFPREGS/SETFPREGS/NT_FPREGSET)
* fix(axbuild): swap debugfs symlink args to link-path-first order
The debugfs symlink command expects "symlink <link_path> <target>"
matching mke2fs convention. Also harden the x86_64 ptrace test with
canary-fork cleanup detection and kernel fault regexes.
* fix(starry-kernel): detach live tracees when tracer exits
* fix(starry-kernel): align x86 ptrace fp snapshots
* fix(starry-kernel): stabilize x86 native gdb ptrace flow
* fix(starry-kernel): clean up ptrace gdb follow-up fixes
* fix(starry-mm): fix file_read_offset computation for unaligned COW split
When vaddr < file_vaddr_base (page-aligned-down start in
unaligned mappings), the saturating_sub returned 0 instead of
correctly subtracting the gap from file_start. This caused
wrong file data to be read after mprotect-induced VMA splits.
Fixes bug-unaligned-cow-split test failure on loongarch64.
* fix(starry-kernel): fix clippy manual_is_multiple_of warning
* fix(starry-mm): extend file_end to cover PT_TLS init image and add execve diagnostics
- map_elf(): scan PT_TLS segments and extend last PT_LOAD file_end
so the COW backend can serve TLS init-image page faults for
the dynamic linker. Without this, ldso sees zeroed TLS data
on riscv64, leading to pc=0 crashes after execve.
- execve: add diagnostic logging for entry/sp/tp/ldso presence
to help debug future user-mode startup failures.
* fix(starry-mm): add AT_NULL auxv terminator to prevent ldso out-of-bounds scan
The auxv constructed in ElfLoader::load() was missing the AT_NULL
(type=0) terminator that the musl dynamic linker uses to stop scanning.
Without it, ld-musl reads past the auxv array into environment string
data on the stack, interpreting arbitrary bytes as auxv entries.
The second exec in init.sh ("exec /bin/sh -l -i") inherits env vars
from the first shell, reshaping the stack so that the out-of-bounds
scan hits garbage aliasing AT_PHDR or AT_ENTRY, producing pc=0 SIGSEGV
with exit code 139. The first exec succeeds only by coincidence — its
empty envp produces a less harmful stack layout.
Fix: push AuxEntry::new(AuxType::NULL, 0) after AT_HWCAP to properly
terminate the auxv.
* chore(ci): re-trigger CI
* test(starry): add SIGSEGV detection to board test fail_regex patterns
OrangePi-5-Plus and SG2002 board tests were timing out after 300-600s
because SIGSEGV crashes (busybox mesg, busybox shell) were not caught
by fail_regex, so the runner waited for the full timeout instead of
failing fast.
Add three patterns to all board test TOMLs:
- '(?i)segmentation fault'
- '(?i)SIGSEGV'
- 'exit with code: 139'
This ensures that any userspace SIGSEGV during boot/login is detected
immediately instead of being hidden behind a timeout.
* chore(ci): re-trigger CI after rustc segfault flake
* fix(starry-mm): add AT_NULL auxv terminator and execve/loader diagnostics
- ElfLoader::load(): add AuxType::NULL terminator to the auxv Vec
- Add info! diagnostic for entry/auxv_count/ldso/last_auxv_type
- execve: upgrade to info! with image name for crash correlation
- map_elf(): downgrade PT_TLS log to debug!
* fix(starry-mm): flush I-cache after populating executable pages on riscv64
On real hardware with non-coherent L1 I/D caches (T-Head C906 on
SG2002), a recycled physical frame from a prior exec may still
hold stale instruction-cache lines. New code bytes written via
D-cache stores by the COW backend are invisible to the I-cache
unless fence.i is executed, causing the CPU to fetch garbage
instructions and jump to pc=0.
Add fence.i (flush_icache_all) in handle_page_fault after
populating any page with EXECUTE permission. QEMU has no real
caches so this is a nop in simulation.
Also replace the stale 'TDOO: flush the I-cache' comment in
loader.rs with a note that coherence is now maintained at
fault time.
* fix(starry-mm): write back D-cache after populating executable pages on XuanTie C9xx
The SG2002 (T-Head C906) board test kept SIGSEGV-ing with pc=0 inside
ld-musl's _dlstart, even after the auxv terminator fix and an added
fence.i. Root cause: the C9xx L1 D-cache is write-back and `fence.i`
does not clean it to the point of unification. The COW backend writes
freshly-faulted code bytes into a frame through the cacheable kernel
linear mapping (phys_to_virt), leaving them in dirty D-cache lines.
The subsequent fence.i on user entry only invalidates the I-cache, so
the instruction fetch refills from stale memory and executes garbage,
jumping to 0. QEMU has no real caches, which is why it only fails on
the board.
- axcpu/riscv: add clean_dcache_range_to_pou(), a th.dcache.cva loop
(per 64-byte line) followed by th.sync.s, gated on xuantie-c9xx.
Opcodes 0x0295000b / 0x0190000b match Linux thead errata.c.
- cow backend: after populating/copying an executable page, clean the
written kernel mapping to the PoU on riscv64 so the I-fetch (after the
existing fence.i in UserContext::run) sees the new code.
- Drop the earlier ineffective fence.i in handle_page_fault; run()
already issues fence.i before every user entry, and the missing piece
was the D-cache writeback, not another I-cache invalidate.
* chore(starry-mm): dump full auxv and entry bytes for SG2002 crash triage
Temporary diagnostic: the SG2002 board still SIGSEGVs at pc=0 in
ld-musl _dlstart despite the cache-coherence fixes, and the entry
instructions execute (gp is set) before the jump to 0. To distinguish a
bad auxv (e.g. AT_ENTRY/AT_PHDR/AT_BASE) from corrupted loaded code
bytes, log every auxv entry and force-populate + hexdump the first 16
bytes at both the ldso entry and AT_ENTRY. To be reverted once root
cause is known.
* fix(starry-mm): read unaligned COW segment first page from correct file offset
The real cause of the SG2002 (and any dynamic-binary) pc=0 SIGSEGV in
ld-musl: commit 82b289c changed alloc_new_at()/file_info() so that when
vaddr < file_vaddr_base (the page-aligned-down first page of a segment
whose p_vaddr/p_offset is not page-aligned) the file offset was computed
as file_start - (file_vaddr_base - vaddr) instead of file_start.
For ld-musl the RW PT_LOAD is at vaddr=0x94b20 (holding .dynamic/GOT).
Its first page (0x94000) took the buggy branch and read the segment
bytes 0xb20 too early in the file, corrupting .dynamic/GOT. The dynamic
linker's RELATIVE self-relocation then produced garbage pointers and
jumped to 0 — deterministically, on the very first dynamic exec. The
ldso/app code pages themselves loaded fine (verified by dumping the
entry bytes), so this was never a cache-coherence problem.
The mapping invariant is simply: virtual address V maps to file offset
file_start + (V - file_vaddr_base). Restore the unified
`file_start + saturating_sub(vaddr, file_vaddr_base)` form (== the
pre-82b289cb1 code), which yields file_start for the unaligned first
page and the correct delta elsewhere. CowBackend::split keeps
file_vaddr_base/file_start intact, so the bug-unaligned-cow-split test
(which only reads page-aligned blob pages, all >= file_vaddr_base, via
the unchanged >= path) is unaffected.
Also revert the speculative XuanTie D-cache writeback and the auxv/byte
diagnostics added while chasing the wrong (cache) hypothesis.
* chore(ci): trigger CI after sync with main
* chore(starry): add proc maps area diagnostics for bug-proc-maps-lseek-refresh
* fix(starry): fix bug-proc-maps-lseek-refresh test failure
Two fixes:
1. pseudofs/proc: render_thread_maps() used '?' on backend.file_info()
which aborted the entire area iteration when an area had no name
or file backing (e.g. PROT_NONE guard pages). Use
unwrap_or_else() with a default-empty BackendFileInfo instead
so all VMAs always appear in /proc/self/maps.
2. test/proc-maps: the test's has_vma_prefix() used %08lx which
produces 8-hex-digit addresses, but the kernel uses {:016x}
(16 hex digits on 64-bit). Use %0*lx with addr_width =
sizeof(void*)*2 to match the kernel's output format.
* fix: resolve merge conflicts with upstream/dev PR rcore-os#1167
- Remove duplicate ProcMemFile (old WeakAxTaskRef version)
- Remove duplicate 'mem' node in ThreadDir
- Accept upstream per-TID ptrace refactor for task/mod.rs, signal.rs, user.rs
- Keep our render_thread_maps file_info() unwind fix
* fix: complete per-TID ptrace API migration and execve stop semantics
- ptrace.rs: migrate x86_64 FP regset paths from old process-wide
ptrace_stop_fp_data()/set_ptrace_stop_fp_data() to per-TID
ptrace_stop_fp_data_for(tid)/set_ptrace_stop_fp_data_for(tid, ...)
using raw [u64;32] bytes to bridge FxsaveArea ↔ arch-independent
PtraceStopRecord storage.
- execve.rs: fix PTRACE_TRACEME exec-stop semantics. Linux requires
TRACEME'd tasks to always generate a SIGTRAP stop on execve;
PTRACE_O_TRACEEXEC only controls whether the stop carries
PTRACE_EVENT_EXEC. Move the TRACEME check outside the TRACEEXEC
option gate.
- reports: fix trailing whitespace and EOF blank lines for
diff --check compliance.
* fix(starry-kernel): correct x86_64 ptrace single-step, exec-stop and register reporting
- user.rs: arm x86_64 hardware single-step (RFLAGS.TF) for traced tracees, and
route the resulting #DB to a SIGTRAP ptrace-stop that disarms the per-TID
single-step flag and clears the saved TF (the CPU pushes EFLAGS with TF still
set), so a subsequent PTRACE_CONT runs free instead of single-stepping.
- axcpu/x86_64/trap.rs: drop the panic on an unhandled #DB; let it fall through
to the user-space exception loop (kprobe/uprobe debug handlers still win).
- ptrace.rs: report Linux-convention user selectors cs=0x33/ss=0x2b via
GETREGS/GETREGSET and accept them in SETREGS so debuggers detect a 64-bit
inferior instead of i386; correct the single-step TF comment.
- execve.rs: every ptrace tracee stops with SIGTRAP on execve (PTRACE_O_TRACEEXEC
only controls the event payload, not whether the stop occurs).
- proc.rs: drop a duplicate /proc/<pid>/mem entry in the thread dir listing.
* test(starry): convert test-gdb-native-batch to a raw-ptrace tracer
Replace the real /usr/bin/gdb driver with a self-contained raw-ptrace tracer
(matching riscv's test-ptrace-gdb), validating the kernel's ptrace on a
dynamically-linked process across execve and ld-musl startup without depending
on GDB's startup probes or target-description negotiation:
fork + PTRACE_TRACEME + execve(dynamic target) -> exec-stop -> read AT_ENTRY
from /proc/<pid>/auxv -> plant INT3 at AT_ENTRY -> PTRACE_CONT (ld-musl runs
fully under ptrace) -> trap at the application entry -> restore + single-step
-> PTRACE_CONT to exit 0.
- add c/src/tracer.c; CMakeLists builds both the dynamic target and the tracer
- qemu-x86_64.toml runs the tracer; success "DONE: N pass, 0 fail"
- remove gdb-native-batch.gdb, run-gdb-native-batch.sh, prebuild.sh (no gdb)
* test(starry): migrate x86 ptrace/gdb cases into grouped system and fix exec-stop path
Move 5 x86 ptrace/gdb test cases from undiscovered normal/qemu-smp1/ to
qemu-smp1/system/ with arch-filtered CMakeLists that install into
starry-test-suit, making them participate in the grouped CI runner.
- test-ptrace-x86-regs: remove canary fork, return exit code directly
- test-ptrace-x86-breakpoint: fix printf format string
- test-gdb-native-batch: split into tracer (starry-test-suit) and
target (usr/bin), rename to test-gdb-native-batch-tracer
Promote test-ptrace-exec-stop from starry-known-fail / riscv-only to
starry-test-suit on riscv64|x86_64. Fix hardcoded path by using
/proc/self/exe so the re-exec child finds itself under the grouped
install location.
Delete stray test-ptrace-exec-stop/qemu-x86_64.toml (double discovery).
Verified: x86_64 and riscv64 grouped system both PASS, all ptrace
binaries show STARRY_SYSTEM_TEST_PASSED.
* chore(ci): re-trigger CI after roc-rk3568 board u-boot flake
* ci: trigger test run
* ci: trigger test run
* chore: remove accidentally committed internal ptrace/gdb reports
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(axbuild): tolerate slow guests in host HTTP test server
The apk-curl-equivalence system case downloads a 20MB payload from the
host HTTP server. The server used a 1s per-write timeout and silently
discarded write errors, so whenever a slow guest (notably x86_64, the
slowest QEMU guest) applied TCP backpressure for over a second, the body
write timed out, the error was dropped, and the connection was closed
mid-stream. curl then failed with "(18) end of response with N bytes
missing", flaking the x86_64 starry qemu test.
Raise the body write timeout to 30s (still finite so a wedged guest
cannot block the server thread and its Drop/join forever) and surface
write errors instead of swallowing them.
* test(starry): wire x86 ptrace/gdb cases into grouped system runner
The new x86_64 ptrace/gdb system cases were laid out as
system/<case>/c/CMakeLists.txt + c/src/, but the qemu-smp*/system
grouped runner builds one root CMake project that only add_subdirectory()
each subcase whose CMakeLists.txt sits directly under system/<case>.
As a result these cases were never built/installed in aggregate runs and
`-c qemu-smp1/system/<case>` failed at configure time with
"unknown grouped C subcase".
Move each case to the flat system subcase layout required by
test-suit/starryos/GUIDE.md (CMakeLists.txt + src/ at the case root) and
fix the relative include of common/starry_arch_filter.cmake accordingly.
Install destinations are unchanged.
Cases: test-ptrace-x86-regs, test-ptrace-x86-breakpoint,
test-ptrace-x86-breakpoint-reinsert, test-ptrace-x86-singlestep,
test-gdb-native-batch.
* fix(starry-kernel): rebase x86_64 ptrace onto upstream/dev per-tid baseline
Replace ptrace.rs with upstream/dev version as baseline and port x86_64 code:
- Add X8664UserRegs struct + From<UserContext>/write_to/sanitize_eflags
- Add X86_64_USER_* constants + peeksuser/pokeuser/user_area_x86_64
- Add x86_64 getregs/setregs/getfpregs/setfpregs/getregset/setregset impls
- Add ptrace_setup_singlestep for x86_64 (RFLAGS.TF)
- Wire x86_64 into multi-arch dispatch gates (NT_FPREGSET/NT_PRSTATUS)
- Define x86_64 PtraceStopFpData as tuple struct + real fxsave/fxrstor
- Add x86_64 to signal.rs ptrace FP save and mod.rs save/restore
Fixes three build-blocking issues:
- ptrace_restore_singlestep_insn present for all archs (from upstream baseline)
- ptrace_setup_singlestep present for aarch64/loongarch64 (from upstream baseline)
- x86_64 FP type matches between ptrace.rs and mod.rs (tuple struct)
* fix(starry-kernel): store full FxsaveArea in x86_64 PtraceStopFpData
Replace PtraceStopFpData([u64; 32], usize) with PtraceStopFpData(FxsaveArea)
to match the 512-byte FXSAVE area. Fixes out-of-bounds memory access at
4 call sites where from_raw_parts(ptr, 512) was created from a 256-byte
[u64; 32] array — UB when the slice exceeded the allocation.
save/restore/GETFPREGS/SETFPREGS/NT_FPREGSET now directly copy the full
FxsaveArea, preserving all XMM/MXCSR state.
* fix(starry): downgrade loader/execve logs to debug, restore kernel #DB panic, add TLS contiguity comment
* test(starry): add x86_64 ptrace FP register coverage
Exercises PTRACE_GETFPREGS/SETFPREGS and NT_PRFPREG round-trip on x86_64,
checking xmm0, xmm10 (offset 320) and xmm15 (offset 400) so a regression that
preserves only part of the 512-byte FXSAVE area is caught. The child loads
known XMM values and stops via a direct kill() syscall to avoid libc clobbering
the registers; the tracer verifies the read-back, writes sentinels, and the
child confirms them after resume. Auto-discovered under qemu-smp1/system.
* fix(starry-kernel): remove duplicate ptrace_setregset_prstatus, fix axnet typo and register call
* chore: fmt execve.rs register call
* fix(starry-kernel): remove unused VirtAddr and DirectRwFsFileOps imports in proc.rs
* chore: fmt proc.rs import line
* fix(starry-kernel): gate format_statm/format_status_vm_lines with cfg(test)
* fix(starry-kernel): gate alloc::format import with cfg(test)
* chore: reorder stats.rs imports for fmt
* fix(starry-kernel): scope ptrace get/setfpregs cfg to all non-x86 arches
ptrace_getfpregs/ptrace_setfpregs use the generic ArchFpRegs path for the
non-x86 architectures, but the supported arm was gated on
any(riscv64, loongarch64) (missing aarch64) while the Unsupported fallback
was gated on not(any(riscv64, x86_64)). On loongarch64 both arms matched,
causing E0428 (duplicate definition); on aarch64 the function fell through
to the Unsupported stub instead of the real ArchFpRegs path. Widen the
supported arm to any(riscv64, aarch64, loongarch64) and the fallback to
not(any(riscv64, aarch64, loongarch64, x86_64)), matching get/setregs.
* fix(starry-kernel): restore /proc features dropped by a bad merge revert
During an earlier conflict resolution, pseudofs/proc.rs was reverted to a
pre-refactor version, silently dropping upstream features: /proc/<pid>/mem
(ProcMemFile + read_at/write_at/check_access), /proc/<pid>/status memory
stats (sample_mem_stats, TaskStatusBase/TaskStatusFields) and the namespace
directory (NsDir), plus their tests. Restore the current upstream/dev proc.rs
and re-apply the only two genuine branch-local tweaks on top: the extended
loongarch /proc/cpuinfo Feat flags, and /proc/<pid>/maps full-width addresses
with anonymous-mapping file_info tolerance.
* fix(axbuild): restore upstream overlay symlink injection
An earlier divergence replaced the two-pass overlay debugfs injection with a
single-pass variant, dropping two upstream behaviours: deferring symlink
creation until after their targets are written (debugfs validates the target),
and converting relative symlink targets to absolute guest paths. Restore the
upstream/dev implementation (which already uses link-path-first symlink args).
* fix(starry-kernel): un-gate ProcessMemStats format methods for /proc
format_statm and format_status_vm_lines had been marked #[cfg(test)] back when
the reverted proc.rs no longer called them (to avoid dead_code under -D warnings).
The restored proc.rs uses both in the real build (/proc/<pid>/statm and
/proc/<pid>/status), so the test-only gating broke non-x86 builds with E0599.
Restore upstream/dev stats.rs so the methods are available in all builds.
* chore: remove accidentally committed GitHub page snapshot
A 172KB GitHub page snapshot (Feat_x86 64 ptrace clean ... rcore-os_tgoskits@f4d00dd.html)
was swept into the branch by a stray 'git add .'. It is not source/test asset and
makes 'git diff --check' fail on trailing whitespace/EOF blank lines. Remove it and
gitignore these page snapshots so they cannot be re-committed.
* fix(starry): use STARRY_ROOTFS in gdb app prebuild
starry app qemu injects the rootfs image path as STARRY_ROOTFS, not
STARRY_BASE_ROOTFS, so the gdb prebuild failed require_env and the
GDB_SMOKE_PASSED qemu path never ran. Match the ffmpeg/pip/mosquitto apps:
read ${STARRY_ROOTFS:-${STARRY_BASE_ROOTFS:-}} and require STARRY_ROOTFS.
* refactor(starry-kernel): converge x86_64 GP registers into ArchUserRegs explicit-TID backend
- Add ArchUserRegs alias for x86_64
- Make write_to return AxResult<()> for all archs
- Expand generic read/write backends to cover x86_64
- Remove parallel x86_64 helper functions
- Unify getregs/setregs into single generic bodies
- Remove inline arch dispatch from getregset/setregset_prstatus
- Update PEEKUSER/POKEUSER user-area to generic backend
- Remove redundant selected-stop wrappers from detach_live_tracees_of
* fix(starry): use dynamic platform for gdb x86_64 app build config
The gdb app x86_64 build config pinned the legacy static x86 platform
(ax-hal/x86-pc, ax-driver/plat-static, the qemu feature, plat_dyn=false).
x86_64 Starry runs on the dynamic platform path, which registers no static
platform package, so 'cargo xtask starry app qemu -t gdb --arch x86_64'
failed at build-config with 'no default platform package is registered for
arch x86_64' and the GDB_SMOKE_PASSED path was unreachable. Drop the static
deps and match the other Starry x86_64 app configs (git/top): keep only the
virtio driver features on the dynamic platform. Verified end-to-end in the
container: boots to a shell, gdb 16.3 runs, GDB_SMOKE_PASSED.
* chore(repo): remove unused workspace crates (rcore-os#1306)
* feat(axbuild): internalize Starry kallsyms flow (rcore-os#1309)
* fix(ci): bump smoke-vmx QEMU timeout 180→600s for self-hosted KVM runner (rcore-os#1315)
Signed-off-by: 林晨 (Leo Cheng) <chengkelfan@qq.com>
* fix(starry): correct x86_64 u_debugreg offset in struct user
x86_64 PTRACE_PEEKUSER/POKEUSER on the debug-register area used
X86_64_USER_DEBUGREG_OFFSET = 912, but u_debugreg[] sits at offset 848 in
the x86_64 `struct user` (regs 216 + u_fpvalid/pad 8 + i387 512 + tsize/
dsize/ssize 24 + start_code/start_stack 16 + signal 8 + reserved/pad 8 +
u_ar0 8 + u_fpstate 8 + magic 8 + comm 32 = 848).
gdbserver probes the hardware debug registers (DR0–DR7) via PEEKUSER at
this offset during startup; with the wrong offset it read a bogus location
and stalled before printing "Listening on port 1234", so the x86_64
gdbserver smoke hung. The native single-process GDB smoke does not touch
debug registers, which is why only the gdbserver path was affected.
Fix the offset to 848. Verified end-to-end in the container: the x86_64
gdbserver smoke now reaches GDBSERVER_SMOKE_DONE.
* feat(gdb-smoke): port GDB and gdbserver smoke to x86_64
参照现有 riscv64/aarch64/loongarch64 实现,为 gdb-smoke 增加 x86_64 的
原生 GDB 冒烟与单进程 gdbserver 冒烟移植:
- 新增 build-x86_64-unknown-none.toml 与默认 qemu-x86_64.toml(native
批量冒烟,成功标志 GDB_NATIVE_SMOKE_DONE);
- 补齐 gdbserver 全套:qemu-x86_64-gdbserver.toml(默认 gdbserver 冒烟,
GDBSERVER_SMOKE_DONE)、gdbserver-host.toml、gdbserver-manual.toml,以及
host-remote-x86_64.gdb / host-manual-x86_64.gdb(set architecture
i386:x86-64);
- prebuild.sh 的 find_qemu_runner 增加 x86_64 分支(qemu-x86_64 +
x86_64-linux-musl);
- README 补充 x86_64 native 与 gdbserver 用法。
gdbserver 路径依赖同分支的 x86_64 u_debugreg 偏移修复才能跑通。已在容器内
验证:native 冒烟 GDB_NATIVE_SMOKE_DONE、gdbserver 冒烟 GDBSERVER_SMOKE_DONE
均通过(断点/backtrace/continue/远程连接/正常退出全部正确)。
---------
Signed-off-by: 林晨 (Leo Cheng) <chengkelfan@qq.com>
Co-authored-by: 54dK3n <ken@kendeAir.lan>
Co-authored-by: 54dK3n <ken@kendeMacBook-Air.local>
Co-authored-by: 54dK3n <ken@ac-c9-06-23-1e-48.walkup.net.uq.edu.au>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: 周睿 <34859362+ZR233@users.noreply.github.com>
Co-authored-by: 禾可 <chengkelfan@qq.com>
* feat(starry-kernel): x86_64 ptrace register r/w and PTRACE_SINGLESTEP support
补齐 x86_64 ptrace 主干功能:
- 新增 `X8664UserRegs` 结构体 (repr(C)),对应 Linux
`user_regs_struct`,含 r15..rsp/ss/fs_base/gs_base 全部 27 个字段
- 实现 `From<UserContext> for X8664UserRegs` 和 `write_to()`
- 补齐 x86_64 上之前缺失的 ptrace opcode:
GETREGS / SETREGS / GETREGSET(NT_PRSTATUS) / SETREGSET(NT_PRSTATUS) /
GETSIGINFO / SETSIGINFO
- 将 `ptrace_getregset_prstatus` 中 `regs` 局部变量从内部 block 提升到
函数级作用域,修复 reg_bytes slice 的 use-after-free bug(regs 出 block
后被栈复用覆盖,导致用户态读到随机值,表现为 RSP=0x1)
- 新增 `ptrace_setup_singlestep` for x86_64:设置 RFLAGS 的 TF (bit 8)
触发 CPU 单步执行
- 为 x86_64 添加 singlestep setup 调用(之前仅 riscv64)
- 新增 `ExceptionKind::Debug` 处理分支:命中 traced task 的 #DB
异常时,清除 TF 并调用 ptrace_stop_current(SIGTRAP)
- Intel SDM 规定 CPU 在交付 TF 诱导的 #DB 时会清除 pushed RFLAGS
中的 TF,但 QEMU 不完全遵守,故显式清除防止 resume 后再次单步
| 测试 | 验证内容 |
|------|----------|
| test-ptrace-x86-regs | TRACEME -> GETREGS/GETREGSET/SETREGS/SETREGSET 闭环 |
| test-ptrace-exec-stop | TRACEME + execve -> SIGTRAP + DETACH |
| test-ptrace-x86-breakpoint | 双测试:software int3 最小闭环 + SINGLESTEP 基础验证 |
| test-ptrace-x86-singlestep | PTRACE_SINGLESTEP 执行一条指令后以 SIGTRAP stop |
| test-ptrace-x86-breakpoint-reinsert | gdb 风格断点恢复:rewind RIP -> 恢复原字节 -> SINGLESTEP -> 重新插入断点 -> 再次命中 |
| test-gdb-native-batch | gdb -q -batch 端到端:break native_marker / run / bt / info registers / continue |
所有 6 个 x86_64 ptrace case 全部通过。
* feat(starry): add gdb smoke test app and update mount-umount2 compat docs
- apps/starry/gdb: gdb --version smoke test for x86_64 QEMU
(qemu-x86_64.toml, build-x86_64-unknown-none.toml, prebuild.sh)
- docs: update mount-umount2 Linux compat documentation with
shared/private/slave/unbindable propagation, bind subdirectory,
MS_MOVE ELOOP, MS_REMOUNT|MS_BIND|MS_RDONLY semantics
* fix(starry-kernel): gate #DB handler behind #[cfg(target_arch = "x86_64")]
ExceptionKind::Debug and uctx.rflags only exist on x86_64, but the
Debug exception handler in user.rs had no cfg guard, leaking x86_64
single-step logic into all architecture builds. Wrap the entire
block in #[cfg(target_arch = "x86_64")].
Fixes CI failures on loongarch64/aarch64/riscv64.
* test(starryos): extend gdb batch timeout
* test(starryos): isolate gdb apk install stage
* fix(starry-kernel): harden x86_64 ptrace reg writes
* fix(starryos): bundle gdb runtime for batch test
* fix(apps): replace docker-run gdb install with qemu-user + native apk
The prebuild script used 'docker run alpine:edge apk add gdb' which requires
the Docker daemon that is not available inside the CI container. Switch to
qemu-x86_64-static + native apk, consistent with gdb-smoke/prebuild.sh.
* fix(apps): use musl ld directly instead of qemu-user for same-arch x86_64 gdb install
qemu-x86_64-static hangs when emulating x86_64 binaries on an x86_64
host during network-heavy operations like 'apk' package downloads. Use
the musl dynamic linker (ld-musl-x86_64.so.1) from the staging rootfs
to run Alpine apk natively without any emulation layer.
* fix(apps): fix gdb app prebuild with musl ld and complete runtime assets
Replace docker-run-based gdb install with native musl ld execution
of Alpine apk, fixing DNS resolution for the staging root.
Add missing gdb/Python runtime assets to overlay:
- /usr/share/gdb/ (gdb Python modules, syscalls, system-gdbinit)
- /usr/lib/python3.12/ (Python stdlib)
- /usr/lib/python312.zip
- libpython3.12.so*
- /usr/bin/python3
* fix(apps): enable virtio-blk and virtio-net drivers for gdb app
The build config only had the 'qemu' feature which does not
automatically enable virtio drivers. Without ax-driver/virtio-blk,
the kernel cannot detect the root block device, causing:
'failed to determine root device from available block devices'
Align with gdb-smoke's build config by adding the required
ax-driver/virtio-blk and ax-driver/virtio-net features.
* fix(apps): add missing virtio-gpu, virtio-input, virtio-socket features
Align gdb app build config with gdb-smoke and test-suit configs.
* fix(axbuild): handle symlinks in overlay injection via debugfs
CMake install(PROGRAMS ...) preserves symlinks from the staging
rootfs, which causes inject_overlay to fail with:
'unsupported overlay entry ... only regular files and directories
are supported'
When a symlink is encountered during overlay traversal, use debugfs
symlink command to create the symbolic link in the target ext4 image
instead of bailing out.
* chore(ci): trigger re-run
* chore(ci): trigger re-run 2
* fix(starry-kernel): add x86_64 ptrace FP register support (GETFPREGS/SETFPREGS/NT_FPREGSET)
* fix(axbuild): swap debugfs symlink args to link-path-first order
The debugfs symlink command expects "symlink <link_path> <target>"
matching mke2fs convention. Also harden the x86_64 ptrace test with
canary-fork cleanup detection and kernel fault regexes.
* fix(starry-kernel): detach live tracees when tracer exits
* fix(starry-kernel): align x86 ptrace fp snapshots
* fix(starry-kernel): stabilize x86 native gdb ptrace flow
* fix(starry-kernel): clean up ptrace gdb follow-up fixes
* fix(starry-mm): fix file_read_offset computation for unaligned COW split
When vaddr < file_vaddr_base (page-aligned-down start in
unaligned mappings), the saturating_sub returned 0 instead of
correctly subtracting the gap from file_start. This caused
wrong file data to be read after mprotect-induced VMA splits.
Fixes bug-unaligned-cow-split test failure on loongarch64.
* fix(starry-kernel): fix clippy manual_is_multiple_of warning
* fix(starry-mm): extend file_end to cover PT_TLS init image and add execve diagnostics
- map_elf(): scan PT_TLS segments and extend last PT_LOAD file_end
so the COW backend can serve TLS init-image page faults for
the dynamic linker. Without this, ldso sees zeroed TLS data
on riscv64, leading to pc=0 crashes after execve.
- execve: add diagnostic logging for entry/sp/tp/ldso presence
to help debug future user-mode startup failures.
* fix(starry-mm): add AT_NULL auxv terminator to prevent ldso out-of-bounds scan
The auxv constructed in ElfLoader::load() was missing the AT_NULL
(type=0) terminator that the musl dynamic linker uses to stop scanning.
Without it, ld-musl reads past the auxv array into environment string
data on the stack, interpreting arbitrary bytes as auxv entries.
The second exec in init.sh ("exec /bin/sh -l -i") inherits env vars
from the first shell, reshaping the stack so that the out-of-bounds
scan hits garbage aliasing AT_PHDR or AT_ENTRY, producing pc=0 SIGSEGV
with exit code 139. The first exec succeeds only by coincidence — its
empty envp produces a less harmful stack layout.
Fix: push AuxEntry::new(AuxType::NULL, 0) after AT_HWCAP to properly
terminate the auxv.
* chore(ci): re-trigger CI
* test(starry): add SIGSEGV detection to board test fail_regex patterns
OrangePi-5-Plus and SG2002 board tests were timing out after 300-600s
because SIGSEGV crashes (busybox mesg, busybox shell) were not caught
by fail_regex, so the runner waited for the full timeout instead of
failing fast.
Add three patterns to all board test TOMLs:
- '(?i)segmentation fault'
- '(?i)SIGSEGV'
- 'exit with code: 139'
This ensures that any userspace SIGSEGV during boot/login is detected
immediately instead of being hidden behind a timeout.
* chore(ci): re-trigger CI after rustc segfault flake
* fix(starry-mm): add AT_NULL auxv terminator and execve/loader diagnostics
- ElfLoader::load(): add AuxType::NULL terminator to the auxv Vec
- Add info! diagnostic for entry/auxv_count/ldso/last_auxv_type
- execve: upgrade to info! with image name for crash correlation
- map_elf(): downgrade PT_TLS log to debug!
* fix(starry-mm): flush I-cache after populating executable pages on riscv64
On real hardware with non-coherent L1 I/D caches (T-Head C906 on
SG2002), a recycled physical frame from a prior exec may still
hold stale instruction-cache lines. New code bytes written via
D-cache stores by the COW backend are invisible to the I-cache
unless fence.i is executed, causing the CPU to fetch garbage
instructions and jump to pc=0.
Add fence.i (flush_icache_all) in handle_page_fault after
populating any page with EXECUTE permission. QEMU has no real
caches so this is a nop in simulation.
Also replace the stale 'TDOO: flush the I-cache' comment in
loader.rs with a note that coherence is now maintained at
fault time.
* fix(starry-mm): write back D-cache after populating executable pages on XuanTie C9xx
The SG2002 (T-Head C906) board test kept SIGSEGV-ing with pc=0 inside
ld-musl's _dlstart, even after the auxv terminator fix and an added
fence.i. Root cause: the C9xx L1 D-cache is write-back and `fence.i`
does not clean it to the point of unification. The COW backend writes
freshly-faulted code bytes into a frame through the cacheable kernel
linear mapping (phys_to_virt), leaving them in dirty D-cache lines.
The subsequent fence.i on user entry only invalidates the I-cache, so
the instruction fetch refills from stale memory and executes garbage,
jumping to 0. QEMU has no real caches, which is why it only fails on
the board.
- axcpu/riscv: add clean_dcache_range_to_pou(), a th.dcache.cva loop
(per 64-byte line) followed by th.sync.s, gated on xuantie-c9xx.
Opcodes 0x0295000b / 0x0190000b match Linux thead errata.c.
- cow backend: after populating/copying an executable page, clean the
written kernel mapping to the PoU on riscv64 so the I-fetch (after the
existing fence.i in UserContext::run) sees the new code.
- Drop the earlier ineffective fence.i in handle_page_fault; run()
already issues fence.i before every user entry, and the missing piece
was the D-cache writeback, not another I-cache invalidate.
* chore(starry-mm): dump full auxv and entry bytes for SG2002 crash triage
Temporary diagnostic: the SG2002 board still SIGSEGVs at pc=0 in
ld-musl _dlstart despite the cache-coherence fixes, and the entry
instructions execute (gp is set) before the jump to 0. To distinguish a
bad auxv (e.g. AT_ENTRY/AT_PHDR/AT_BASE) from corrupted loaded code
bytes, log every auxv entry and force-populate + hexdump the first 16
bytes at both the ldso entry and AT_ENTRY. To be reverted once root
cause is known.
* fix(starry-mm): read unaligned COW segment first page from correct file offset
The real cause of the SG2002 (and any dynamic-binary) pc=0 SIGSEGV in
ld-musl: commit 82b289c changed alloc_new_at()/file_info() so that when
vaddr < file_vaddr_base (the page-aligned-down first page of a segment
whose p_vaddr/p_offset is not page-aligned) the file offset was computed
as file_start - (file_vaddr_base - vaddr) instead of file_start.
For ld-musl the RW PT_LOAD is at vaddr=0x94b20 (holding .dynamic/GOT).
Its first page (0x94000) took the buggy branch and read the segment
bytes 0xb20 too early in the file, corrupting .dynamic/GOT. The dynamic
linker's RELATIVE self-relocation then produced garbage pointers and
jumped to 0 — deterministically, on the very first dynamic exec. The
ldso/app code pages themselves loaded fine (verified by dumping the
entry bytes), so this was never a cache-coherence problem.
The mapping invariant is simply: virtual address V maps to file offset
file_start + (V - file_vaddr_base). Restore the unified
`file_start + saturating_sub(vaddr, file_vaddr_base)` form (== the
pre-82b289cb1 code), which yields file_start for the unaligned first
page and the correct delta elsewhere. CowBackend::split keeps
file_vaddr_base/file_start intact, so the bug-unaligned-cow-split test
(which only reads page-aligned blob pages, all >= file_vaddr_base, via
the unchanged >= path) is unaffected.
Also revert the speculative XuanTie D-cache writeback and the auxv/byte
diagnostics added while chasing the wrong (cache) hypothesis.
* chore(ci): trigger CI after sync with main
* chore(starry): add proc maps area diagnostics for bug-proc-maps-lseek-refresh
* fix(starry): fix bug-proc-maps-lseek-refresh test failure
Two fixes:
1. pseudofs/proc: render_thread_maps() used '?' on backend.file_info()
which aborted the entire area iteration when an area had no name
or file backing (e.g. PROT_NONE guard pages). Use
unwrap_or_else() with a default-empty BackendFileInfo instead
so all VMAs always appear in /proc/self/maps.
2. test/proc-maps: the test's has_vma_prefix() used %08lx which
produces 8-hex-digit addresses, but the kernel uses {:016x}
(16 hex digits on 64-bit). Use %0*lx with addr_width =
sizeof(void*)*2 to match the kernel's output format.
* fix: resolve merge conflicts with upstream/dev PR rcore-os#1167
- Remove duplicate ProcMemFile (old WeakAxTaskRef version)
- Remove duplicate 'mem' node in ThreadDir
- Accept upstream per-TID ptrace refactor for task/mod.rs, signal.rs, user.rs
- Keep our render_thread_maps file_info() unwind fix
* fix: complete per-TID ptrace API migration and execve stop semantics
- ptrace.rs: migrate x86_64 FP regset paths from old process-wide
ptrace_stop_fp_data()/set_ptrace_stop_fp_data() to per-TID
ptrace_stop_fp_data_for(tid)/set_ptrace_stop_fp_data_for(tid, ...)
using raw [u64;32] bytes to bridge FxsaveArea ↔ arch-independent
PtraceStopRecord storage.
- execve.rs: fix PTRACE_TRACEME exec-stop semantics. Linux requires
TRACEME'd tasks to always generate a SIGTRAP stop on execve;
PTRACE_O_TRACEEXEC only controls whether the stop carries
PTRACE_EVENT_EXEC. Move the TRACEME check outside the TRACEEXEC
option gate.
- reports: fix trailing whitespace and EOF blank lines for
diff --check compliance.
* fix(starry-kernel): correct x86_64 ptrace single-step, exec-stop and register reporting
- user.rs: arm x86_64 hardware single-step (RFLAGS.TF) for traced tracees, and
route the resulting #DB to a SIGTRAP ptrace-stop that disarms the per-TID
single-step flag and clears the saved TF (the CPU pushes EFLAGS with TF still
set), so a subsequent PTRACE_CONT runs free instead of single-stepping.
- axcpu/x86_64/trap.rs: drop the panic on an unhandled #DB; let it fall through
to the user-space exception loop (kprobe/uprobe debug handlers still win).
- ptrace.rs: report Linux-convention user selectors cs=0x33/ss=0x2b via
GETREGS/GETREGSET and accept them in SETREGS so debuggers detect a 64-bit
inferior instead of i386; correct the single-step TF comment.
- execve.rs: every ptrace tracee stops with SIGTRAP on execve (PTRACE_O_TRACEEXEC
only controls the event payload, not whether the stop occurs).
- proc.rs: drop a duplicate /proc/<pid>/mem entry in the thread dir listing.
* test(starry): convert test-gdb-native-batch to a raw-ptrace tracer
Replace the real /usr/bin/gdb driver with a self-contained raw-ptrace tracer
(matching riscv's test-ptrace-gdb), validating the kernel's ptrace on a
dynamically-linked process across execve and ld-musl startup without depending
on GDB's startup probes or target-description negotiation:
fork + PTRACE_TRACEME + execve(dynamic target) -> exec-stop -> read AT_ENTRY
from /proc/<pid>/auxv -> plant INT3 at AT_ENTRY -> PTRACE_CONT (ld-musl runs
fully under ptrace) -> trap at the application entry -> restore + single-step
-> PTRACE_CONT to exit 0.
- add c/src/tracer.c; CMakeLists builds both the dynamic target and the tracer
- qemu-x86_64.toml runs the tracer; success "DONE: N pass, 0 fail"
- remove gdb-native-batch.gdb, run-gdb-native-batch.sh, prebuild.sh (no gdb)
* test(starry): migrate x86 ptrace/gdb cases into grouped system and fix exec-stop path
Move 5 x86 ptrace/gdb test cases from undiscovered normal/qemu-smp1/ to
qemu-smp1/system/ with arch-filtered CMakeLists that install into
starry-test-suit, making them participate in the grouped CI runner.
- test-ptrace-x86-regs: remove canary fork, return exit code directly
- test-ptrace-x86-breakpoint: fix printf format string
- test-gdb-native-batch: split into tracer (starry-test-suit) and
target (usr/bin), rename to test-gdb-native-batch-tracer
Promote test-ptrace-exec-stop from starry-known-fail / riscv-only to
starry-test-suit on riscv64|x86_64. Fix hardcoded path by using
/proc/self/exe so the re-exec child finds itself under the grouped
install location.
Delete stray test-ptrace-exec-stop/qemu-x86_64.toml (double discovery).
Verified: x86_64 and riscv64 grouped system both PASS, all ptrace
binaries show STARRY_SYSTEM_TEST_PASSED.
* chore(ci): re-trigger CI after roc-rk3568 board u-boot flake
* ci: trigger test run
* ci: trigger test run
* chore: remove accidentally committed internal ptrace/gdb reports
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(axbuild): tolerate slow guests in host HTTP test server
The apk-curl-equivalence system case downloads a 20MB payload from the
host HTTP server. The server used a 1s per-write timeout and silently
discarded write errors, so whenever a slow guest (notably x86_64, the
slowest QEMU guest) applied TCP backpressure for over a second, the body
write timed out, the error was dropped, and the connection was closed
mid-stream. curl then failed with "(18) end of response with N bytes
missing", flaking the x86_64 starry qemu test.
Raise the body write timeout to 30s (still finite so a wedged guest
cannot block the server thread and its Drop/join forever) and surface
write errors instead of swallowing them.
* test(starry): wire x86 ptrace/gdb cases into grouped system runner
The new x86_64 ptrace/gdb system cases were laid out as
system/<case>/c/CMakeLists.txt + c/src/, but the qemu-smp*/system
grouped runner builds one root CMake project that only add_subdirectory()
each subcase whose CMakeLists.txt sits directly under system/<case>.
As a result these cases were never built/installed in aggregate runs and
`-c qemu-smp1/system/<case>` failed at configure time with
"unknown grouped C subcase".
Move each case to the flat system subcase layout required by
test-suit/starryos/GUIDE.md (CMakeLists.txt + src/ at the case root) and
fix the relative include of common/starry_arch_filter.cmake accordingly.
Install destinations are unchanged.
Cases: test-ptrace-x86-regs, test-ptrace-x86-breakpoint,
test-ptrace-x86-breakpoint-reinsert, test-ptrace-x86-singlestep,
test-gdb-native-batch.
* fix(starry-kernel): rebase x86_64 ptrace onto upstream/dev per-tid baseline
Replace ptrace.rs with upstream/dev version as baseline and port x86_64 code:
- Add X8664UserRegs struct + From<UserContext>/write_to/sanitize_eflags
- Add X86_64_USER_* constants + peeksuser/pokeuser/user_area_x86_64
- Add x86_64 getregs/setregs/getfpregs/setfpregs/getregset/setregset impls
- Add ptrace_setup_singlestep for x86_64 (RFLAGS.TF)
- Wire x86_64 into multi-arch dispatch gates (NT_FPREGSET/NT_PRSTATUS)
- Define x86_64 PtraceStopFpData as tuple struct + real fxsave/fxrstor
- Add x86_64 to signal.rs ptrace FP save and mod.rs save/restore
Fixes three build-blocking issues:
- ptrace_restore_singlestep_insn present for all archs (from upstream baseline)
- ptrace_setup_singlestep present for aarch64/loongarch64 (from upstream baseline)
- x86_64 FP type matches between ptrace.rs and mod.rs (tuple struct)
* fix(starry-kernel): store full FxsaveArea in x86_64 PtraceStopFpData
Replace PtraceStopFpData([u64; 32], usize) with PtraceStopFpData(FxsaveArea)
to match the 512-byte FXSAVE area. Fixes out-of-bounds memory access at
4 call sites where from_raw_parts(ptr, 512) was created from a 256-byte
[u64; 32] array — UB when the slice exceeded the allocation.
save/restore/GETFPREGS/SETFPREGS/NT_FPREGSET now directly copy the full
FxsaveArea, preserving all XMM/MXCSR state.
* fix(starry): downgrade loader/execve logs to debug, restore kernel #DB panic, add TLS contiguity comment
* test(starry): add x86_64 ptrace FP register coverage
Exercises PTRACE_GETFPREGS/SETFPREGS and NT_PRFPREG round-trip on x86_64,
checking xmm0, xmm10 (offset 320) and xmm15 (offset 400) so a regression that
preserves only part of the 512-byte FXSAVE area is caught. The child loads
known XMM values and stops via a direct kill() syscall to avoid libc clobbering
the registers; the tracer verifies the read-back, writes sentinels, and the
child confirms them after resume. Auto-discovered under qemu-smp1/system.
* fix(starry-kernel): remove duplicate ptrace_setregset_prstatus, fix axnet typo and register call
* chore: fmt execve.rs register call
* fix(starry-kernel): remove unused VirtAddr and DirectRwFsFileOps imports in proc.rs
* chore: fmt proc.rs import line
* fix(starry-kernel): gate format_statm/format_status_vm_lines with cfg(test)
* fix(starry-kernel): gate alloc::format import with cfg(test)
* chore: reorder stats.rs imports for fmt
* fix(starry-kernel): scope ptrace get/setfpregs cfg to all non-x86 arches
ptrace_getfpregs/ptrace_setfpregs use the generic ArchFpRegs path for the
non-x86 architectures, but the supported arm was gated on
any(riscv64, loongarch64) (missing aarch64) while the Unsupported fallback
was gated on not(any(riscv64, x86_64)). On loongarch64 both arms matched,
causing E0428 (duplicate definition); on aarch64 the function fell through
to the Unsupported stub instead of the real ArchFpRegs path. Widen the
supported arm to any(riscv64, aarch64, loongarch64) and the fallback to
not(any(riscv64, aarch64, loongarch64, x86_64)), matching get/setregs.
* fix(starry-kernel): restore /proc features dropped by a bad merge revert
During an earlier conflict resolution, pseudofs/proc.rs was reverted to a
pre-refactor version, silently dropping upstream features: /proc/<pid>/mem
(ProcMemFile + read_at/write_at/check_access), /proc/<pid>/status memory
stats (sample_mem_stats, TaskStatusBase/TaskStatusFields) and the namespace
directory (NsDir), plus their tests. Restore the current upstream/dev proc.rs
and re-apply the only two genuine branch-local tweaks on top: the extended
loongarch /proc/cpuinfo Feat flags, and /proc/<pid>/maps full-width addresses
with anonymous-mapping file_info tolerance.
* fix(axbuild): restore upstream overlay symlink injection
An earlier divergence replaced the two-pass overlay debugfs injection with a
single-pass variant, dropping two upstream behaviours: deferring symlink
creation until after their targets are written (debugfs validates the target),
and converting relative symlink targets to absolute guest paths. Restore the
upstream/dev implementation (which already uses link-path-first symlink args).
* fix(starry-kernel): un-gate ProcessMemStats format methods for /proc
format_statm and format_status_vm_lines had been marked #[cfg(test)] back when
the reverted proc.rs no longer called them (to avoid dead_code under -D warnings).
The restored proc.rs uses both in the real build (/proc/<pid>/statm and
/proc/<pid>/status), so the test-only gating broke non-x86 builds with E0599.
Restore upstream/dev stats.rs so the methods are available in all builds.
* chore: remove accidentally committed GitHub page snapshot
A 172KB GitHub page snapshot (Feat_x86 64 ptrace clean ... rcore-os_tgoskits@f4d00dd.html)
was swept into the branch by a stray 'git add .'. It is not source/test asset and
makes 'git diff --check' fail on trailing whitespace/EOF blank lines. Remove it and
gitignore these page snapshots so they cannot be re-committed.
* fix(starry): use STARRY_ROOTFS in gdb app prebuild
starry app qemu injects the rootfs image path as STARRY_ROOTFS, not
STARRY_BASE_ROOTFS, so the gdb prebuild failed require_env and the
GDB_SMOKE_PASSED qemu path never ran. Match the ffmpeg/pip/mosquitto apps:
read ${STARRY_ROOTFS:-${STARRY_BASE_ROOTFS:-}} and require STARRY_ROOTFS.
* refactor(starry-kernel): converge x86_64 GP registers into ArchUserRegs explicit-TID backend
- Add ArchUserRegs alias for x86_64
- Make write_to return AxResult<()> for all archs
- Expand generic read/write backends to cover x86_64
- Remove parallel x86_64 helper functions
- Unify getregs/setregs into single generic bodies
- Remove inline arch dispatch from getregset/setregset_prstatus
- Update PEEKUSER/POKEUSER user-area to generic backend
- Remove redundant selected-stop wrappers from detach_live_tracees_of
* fix(starry): use dynamic platform for gdb x86_64 app build config
The gdb app x86_64 build config pinned the legacy static x86 platform
(ax-hal/x86-pc, ax-driver/plat-static, the qemu feature, plat_dyn=false).
x86_64 Starry runs on the dynamic platform path, which registers no static
platform package, so 'cargo xtask starry app qemu -t gdb --arch x86_64'
failed at build-config with 'no default platform package is registered for
arch x86_64' and the GDB_SMOKE_PASSED path was unreachable. Drop the static
deps and match the other Starry x86_64 app configs (git/top): keep only the
virtio driver features on the dynamic platform. Verified end-to-end in the
container: boots to a shell, gdb 16.3 runs, GDB_SMOKE_PASSED.
* chore(repo): remove unused workspace crates (rcore-os#1306)
* feat(axbuild): internalize Starry kallsyms flow (rcore-os#1309)
* fix(ci): bump smoke-vmx QEMU timeout 180→600s for self-hosted KVM runner (rcore-os#1315)
Signed-off-by: 林晨 (Leo Cheng) <chengkelfan@qq.com>
* fix(starry): correct x86_64 u_debugreg offset in struct user
x86_64 PTRACE_PEEKUSER/POKEUSER on the debug-register area used
X86_64_USER_DEBUGREG_OFFSET = 912, but u_debugreg[] sits at offset 848 in
the x86_64 `struct user` (regs 216 + u_fpvalid/pad 8 + i387 512 + tsize/
dsize/ssize 24 + start_code/start_stack 16 + signal 8 + reserved/pad 8 +
u_ar0 8 + u_fpstate 8 + magic 8 + comm 32 = 848).
gdbserver probes the hardware debug registers (DR0–DR7) via PEEKUSER at
this offset during startup; with the wrong offset it read a bogus location
and stalled before printing "Listening on port 1234", so the x86_64
gdbserver smoke hung. The native single-process GDB smoke does not touch
debug registers, which is why only the gdbserver path was affected.
Fix the offset to 848. Verified end-to-end in the container: the x86_64
gdbserver smoke now reaches GDBSERVER_SMOKE_DONE.
* feat(gdb-smoke): port GDB and gdbserver smoke to x86_64
参照现有 riscv64/aarch64/loongarch64 实现,为 gdb-smoke 增加 x86_64 的
原生 GDB 冒烟与单进程 gdbserver 冒烟移植:
- 新增 build-x86_64-unknown-none.toml 与默认 qemu-x86_64.toml(native
批量冒烟,成功标志 GDB_NATIVE_SMOKE_DONE);
- 补齐 gdbserver 全套:qemu-x86_64-gdbserver.toml(默认 gdbserver 冒烟,
GDBSERVER_SMOKE_DONE)、gdbserver-host.toml、gdbserver-manual.toml,以及
host-remote-x86_64.gdb / host-manual-x86_64.gdb(set architecture
i386:x86-64);
- prebuild.sh 的 find_qemu_runner 增加 x86_64 分支(qemu-x86_64 +
x86_64-linux-musl);
- README 补充 x86_64 native 与 gdbserver 用法。
gdbserver 路径依赖同分支的 x86_64 u_debugreg 偏移修复才能跑通。已在容器内
验证:native 冒烟 GDB_NATIVE_SMOKE_DONE、gdbserver 冒烟 GDBSERVER_SMOKE_DONE
均通过(断点/backtrace/continue/远程连接/正常退出全部正确)。
---------
Signed-off-by: 林晨 (Leo Cheng) <chengkelfan@qq.com>
Co-authored-by: 54dK3n <ken@kendeAir.lan>
Co-authored-by: 54dK3n <ken@kendeMacBook-Air.local>
Co-authored-by: 54dK3n <ken@ac-c9-06-23-1e-48.walkup.net.uq.edu.au>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: 周睿 <34859362+ZR233@users.noreply.github.com>
Co-authored-by: 禾可 <chengkelfan@qq.com>
* feat(starry-kernel): x86_64 ptrace register r/w and PTRACE_SINGLESTEP support
补齐 x86_64 ptrace 主干功能:
- 新增 `X8664UserRegs` 结构体 (repr(C)),对应 Linux
`user_regs_struct`,含 r15..rsp/ss/fs_base/gs_base 全部 27 个字段
- 实现 `From<UserContext> for X8664UserRegs` 和 `write_to()`
- 补齐 x86_64 上之前缺失的 ptrace opcode:
GETREGS / SETREGS / GETREGSET(NT_PRSTATUS) / SETREGSET(NT_PRSTATUS) /
GETSIGINFO / SETSIGINFO
- 将 `ptrace_getregset_prstatus` 中 `regs` 局部变量从内部 block 提升到
函数级作用域,修复 reg_bytes slice 的 use-after-free bug(regs 出 block
后被栈复用覆盖,导致用户态读到随机值,表现为 RSP=0x1)
- 新增 `ptrace_setup_singlestep` for x86_64:设置 RFLAGS 的 TF (bit 8)
触发 CPU 单步执行
- 为 x86_64 添加 singlestep setup 调用(之前仅 riscv64)
- 新增 `ExceptionKind::Debug` 处理分支:命中 traced task 的 #DB
异常时,清除 TF 并调用 ptrace_stop_current(SIGTRAP)
- Intel SDM 规定 CPU 在交付 TF 诱导的 #DB 时会清除 pushed RFLAGS
中的 TF,但 QEMU 不完全遵守,故显式清除防止 resume 后再次单步
| 测试 | 验证内容 |
|------|----------|
| test-ptrace-x86-regs | TRACEME -> GETREGS/GETREGSET/SETREGS/SETREGSET 闭环 |
| test-ptrace-exec-stop | TRACEME + execve -> SIGTRAP + DETACH |
| test-ptrace-x86-breakpoint | 双测试:software int3 最小闭环 + SINGLESTEP 基础验证 |
| test-ptrace-x86-singlestep | PTRACE_SINGLESTEP 执行一条指令后以 SIGTRAP stop |
| test-ptrace-x86-breakpoint-reinsert | gdb 风格断点恢复:rewind RIP -> 恢复原字节 -> SINGLESTEP -> 重新插入断点 -> 再次命中 |
| test-gdb-native-batch | gdb -q -batch 端到端:break native_marker / run / bt / info registers / continue |
所有 6 个 x86_64 ptrace case 全部通过。
* feat(starry): add gdb smoke test app and update mount-umount2 compat docs
- apps/starry/gdb: gdb --version smoke test for x86_64 QEMU
(qemu-x86_64.toml, build-x86_64-unknown-none.toml, prebuild.sh)
- docs: update mount-umount2 Linux compat documentation with
shared/private/slave/unbindable propagation, bind subdirectory,
MS_MOVE ELOOP, MS_REMOUNT|MS_BIND|MS_RDONLY semantics
* fix(starry-kernel): gate #DB handler behind #[cfg(target_arch = "x86_64")]
ExceptionKind::Debug and uctx.rflags only exist on x86_64, but the
Debug exception handler in user.rs had no cfg guard, leaking x86_64
single-step logic into all architecture builds. Wrap the entire
block in #[cfg(target_arch = "x86_64")].
Fixes CI failures on loongarch64/aarch64/riscv64.
* test(starryos): extend gdb batch timeout
* test(starryos): isolate gdb apk install stage
* fix(starry-kernel): harden x86_64 ptrace reg writes
* fix(starryos): bundle gdb runtime for batch test
* fix(apps): replace docker-run gdb install with qemu-user + native apk
The prebuild script used 'docker run alpine:edge apk add gdb' which requires
the Docker daemon that is not available inside the CI container. Switch to
qemu-x86_64-static + native apk, consistent with gdb-smoke/prebuild.sh.
* fix(apps): use musl ld directly instead of qemu-user for same-arch x86_64 gdb install
qemu-x86_64-static hangs when emulating x86_64 binaries on an x86_64
host during network-heavy operations like 'apk' package downloads. Use
the musl dynamic linker (ld-musl-x86_64.so.1) from the staging rootfs
to run Alpine apk natively without any emulation layer.
* fix(apps): fix gdb app prebuild with musl ld and complete runtime assets
Replace docker-run-based gdb install with native musl ld execution
of Alpine apk, fixing DNS resolution for the staging root.
Add missing gdb/Python runtime assets to overlay:
- /usr/share/gdb/ (gdb Python modules, syscalls, system-gdbinit)
- /usr/lib/python3.12/ (Python stdlib)
- /usr/lib/python312.zip
- libpython3.12.so*
- /usr/bin/python3
* fix(apps): enable virtio-blk and virtio-net drivers for gdb app
The build config only had the 'qemu' feature which does not
automatically enable virtio drivers. Without ax-driver/virtio-blk,
the kernel cannot detect the root block device, causing:
'failed to determine root device from available block devices'
Align with gdb-smoke's build config by adding the required
ax-driver/virtio-blk and ax-driver/virtio-net features.
* fix(apps): add missing virtio-gpu, virtio-input, virtio-socket features
Align gdb app build config with gdb-smoke and test-suit configs.
* fix(axbuild): handle symlinks in overlay injection via debugfs
CMake install(PROGRAMS ...) preserves symlinks from the staging
rootfs, which causes inject_overlay to fail with:
'unsupported overlay entry ... only regular files and directories
are supported'
When a symlink is encountered during overlay traversal, use debugfs
symlink command to create the symbolic link in the target ext4 image
instead of bailing out.
* chore(ci): trigger re-run
* chore(ci): trigger re-run 2
* fix(starry-kernel): add x86_64 ptrace FP register support (GETFPREGS/SETFPREGS/NT_FPREGSET)
* fix(axbuild): swap debugfs symlink args to link-path-first order
The debugfs symlink command expects "symlink <link_path> <target>"
matching mke2fs convention. Also harden the x86_64 ptrace test with
canary-fork cleanup detection and kernel fault regexes.
* fix(starry-kernel): detach live tracees when tracer exits
* fix(starry-kernel): align x86 ptrace fp snapshots
* fix(starry-kernel): stabilize x86 native gdb ptrace flow
* fix(starry-kernel): clean up ptrace gdb follow-up fixes
* fix(starry-mm): fix file_read_offset computation for unaligned COW split
When vaddr < file_vaddr_base (page-aligned-down start in
unaligned mappings), the saturating_sub returned 0 instead of
correctly subtracting the gap from file_start. This caused
wrong file data to be read after mprotect-induced VMA splits.
Fixes bug-unaligned-cow-split test failure on loongarch64.
* fix(starry-kernel): fix clippy manual_is_multiple_of warning
* fix(starry-mm): extend file_end to cover PT_TLS init image and add execve diagnostics
- map_elf(): scan PT_TLS segments and extend last PT_LOAD file_end
so the COW backend can serve TLS init-image page faults for
the dynamic linker. Without this, ldso sees zeroed TLS data
on riscv64, leading to pc=0 crashes after execve.
- execve: add diagnostic logging for entry/sp/tp/ldso presence
to help debug future user-mode startup failures.
* fix(starry-mm): add AT_NULL auxv terminator to prevent ldso out-of-bounds scan
The auxv constructed in ElfLoader::load() was missing the AT_NULL
(type=0) terminator that the musl dynamic linker uses to stop scanning.
Without it, ld-musl reads past the auxv array into environment string
data on the stack, interpreting arbitrary bytes as auxv entries.
The second exec in init.sh ("exec /bin/sh -l -i") inherits env vars
from the first shell, reshaping the stack so that the out-of-bounds
scan hits garbage aliasing AT_PHDR or AT_ENTRY, producing pc=0 SIGSEGV
with exit code 139. The first exec succeeds only by coincidence — its
empty envp produces a less harmful stack layout.
Fix: push AuxEntry::new(AuxType::NULL, 0) after AT_HWCAP to properly
terminate the auxv.
* chore(ci): re-trigger CI
* test(starry): add SIGSEGV detection to board test fail_regex patterns
OrangePi-5-Plus and SG2002 board tests were timing out after 300-600s
because SIGSEGV crashes (busybox mesg, busybox shell) were not caught
by fail_regex, so the runner waited for the full timeout instead of
failing fast.
Add three patterns to all board test TOMLs:
- '(?i)segmentation fault'
- '(?i)SIGSEGV'
- 'exit with code: 139'
This ensures that any userspace SIGSEGV during boot/login is detected
immediately instead of being hidden behind a timeout.
* chore(ci): re-trigger CI after rustc segfault flake
* fix(starry-mm): add AT_NULL auxv terminator and execve/loader diagnostics
- ElfLoader::load(): add AuxType::NULL terminator to the auxv Vec
- Add info! diagnostic for entry/auxv_count/ldso/last_auxv_type
- execve: upgrade to info! with image name for crash correlation
- map_elf(): downgrade PT_TLS log to debug!
* fix(starry-mm): flush I-cache after populating executable pages on riscv64
On real hardware with non-coherent L1 I/D caches (T-Head C906 on
SG2002), a recycled physical frame from a prior exec may still
hold stale instruction-cache lines. New code bytes written via
D-cache stores by the COW backend are invisible to the I-cache
unless fence.i is executed, causing the CPU to fetch garbage
instructions and jump to pc=0.
Add fence.i (flush_icache_all) in handle_page_fault after
populating any page with EXECUTE permission. QEMU has no real
caches so this is a nop in simulation.
Also replace the stale 'TDOO: flush the I-cache' comment in
loader.rs with a note that coherence is now maintained at
fault time.
* fix(starry-mm): write back D-cache after populating executable pages on XuanTie C9xx
The SG2002 (T-Head C906) board test kept SIGSEGV-ing with pc=0 inside
ld-musl's _dlstart, even after the auxv terminator fix and an added
fence.i. Root cause: the C9xx L1 D-cache is write-back and `fence.i`
does not clean it to the point of unification. The COW backend writes
freshly-faulted code bytes into a frame through the cacheable kernel
linear mapping (phys_to_virt), leaving them in dirty D-cache lines.
The subsequent fence.i on user entry only invalidates the I-cache, so
the instruction fetch refills from stale memory and executes garbage,
jumping to 0. QEMU has no real caches, which is why it only fails on
the board.
- axcpu/riscv: add clean_dcache_range_to_pou(), a th.dcache.cva loop
(per 64-byte line) followed by th.sync.s, gated on xuantie-c9xx.
Opcodes 0x0295000b / 0x0190000b match Linux thead errata.c.
- cow backend: after populating/copying an executable page, clean the
written kernel mapping to the PoU on riscv64 so the I-fetch (after the
existing fence.i in UserContext::run) sees the new code.
- Drop the earlier ineffective fence.i in handle_page_fault; run()
already issues fence.i before every user entry, and the missing piece
was the D-cache writeback, not another I-cache invalidate.
* chore(starry-mm): dump full auxv and entry bytes for SG2002 crash triage
Temporary diagnostic: the SG2002 board still SIGSEGVs at pc=0 in
ld-musl _dlstart despite the cache-coherence fixes, and the entry
instructions execute (gp is set) before the jump to 0. To distinguish a
bad auxv (e.g. AT_ENTRY/AT_PHDR/AT_BASE) from corrupted loaded code
bytes, log every auxv entry and force-populate + hexdump the first 16
bytes at both the ldso entry and AT_ENTRY. To be reverted once root
cause is known.
* fix(starry-mm): read unaligned COW segment first page from correct file offset
The real cause of the SG2002 (and any dynamic-binary) pc=0 SIGSEGV in
ld-musl: commit 82b289c changed alloc_new_at()/file_info() so that when
vaddr < file_vaddr_base (the page-aligned-down first page of a segment
whose p_vaddr/p_offset is not page-aligned) the file offset was computed
as file_start - (file_vaddr_base - vaddr) instead of file_start.
For ld-musl the RW PT_LOAD is at vaddr=0x94b20 (holding .dynamic/GOT).
Its first page (0x94000) took the buggy branch and read the segment
bytes 0xb20 too early in the file, corrupting .dynamic/GOT. The dynamic
linker's RELATIVE self-relocation then produced garbage pointers and
jumped to 0 — deterministically, on the very first dynamic exec. The
ldso/app code pages themselves loaded fine (verified by dumping the
entry bytes), so this was never a cache-coherence problem.
The mapping invariant is simply: virtual address V maps to file offset
file_start + (V - file_vaddr_base). Restore the unified
`file_start + saturating_sub(vaddr, file_vaddr_base)` form (== the
pre-82b289cb1 code), which yields file_start for the unaligned first
page and the correct delta elsewhere. CowBackend::split keeps
file_vaddr_base/file_start intact, so the bug-unaligned-cow-split test
(which only reads page-aligned blob pages, all >= file_vaddr_base, via
the unchanged >= path) is unaffected.
Also revert the speculative XuanTie D-cache writeback and the auxv/byte
diagnostics added while chasing the wrong (cache) hypothesis.
* chore(ci): trigger CI after sync with main
* chore(starry): add proc maps area diagnostics for bug-proc-maps-lseek-refresh
* fix(starry): fix bug-proc-maps-lseek-refresh test failure
Two fixes:
1. pseudofs/proc: render_thread_maps() used '?' on backend.file_info()
which aborted the entire area iteration when an area had no name
or file backing (e.g. PROT_NONE guard pages). Use
unwrap_or_else() with a default-empty BackendFileInfo instead
so all VMAs always appear in /proc/self/maps.
2. test/proc-maps: the test's has_vma_prefix() used %08lx which
produces 8-hex-digit addresses, but the kernel uses {:016x}
(16 hex digits on 64-bit). Use %0*lx with addr_width =
sizeof(void*)*2 to match the kernel's output format.
* fix: resolve merge conflicts with upstream/dev PR #1167
- Remove duplicate ProcMemFile (old WeakAxTaskRef version)
- Remove duplicate 'mem' node in ThreadDir
- Accept upstream per-TID ptrace refactor for task/mod.rs, signal.rs, user.rs
- Keep our render_thread_maps file_info() unwind fix
* fix: complete per-TID ptrace API migration and execve stop semantics
- ptrace.rs: migrate x86_64 FP regset paths from old process-wide
ptrace_stop_fp_data()/set_ptrace_stop_fp_data() to per-TID
ptrace_stop_fp_data_for(tid)/set_ptrace_stop_fp_data_for(tid, ...)
using raw [u64;32] bytes to bridge FxsaveArea ↔ arch-independent
PtraceStopRecord storage.
- execve.rs: fix PTRACE_TRACEME exec-stop semantics. Linux requires
TRACEME'd tasks to always generate a SIGTRAP stop on execve;
PTRACE_O_TRACEEXEC only controls whether the stop carries
PTRACE_EVENT_EXEC. Move the TRACEME check outside the TRACEEXEC
option gate.
- reports: fix trailing whitespace and EOF blank lines for
diff --check compliance.
* fix(starry-kernel): correct x86_64 ptrace single-step, exec-stop and register reporting
- user.rs: arm x86_64 hardware single-step (RFLAGS.TF) for traced tracees, and
route the resulting #DB to a SIGTRAP ptrace-stop that disarms the per-TID
single-step flag and clears the saved TF (the CPU pushes EFLAGS with TF still
set), so a subsequent PTRACE_CONT runs free instead of single-stepping.
- axcpu/x86_64/trap.rs: drop the panic on an unhandled #DB; let it fall through
to the user-space exception loop (kprobe/uprobe debug handlers still win).
- ptrace.rs: report Linux-convention user selectors cs=0x33/ss=0x2b via
GETREGS/GETREGSET and accept them in SETREGS so debuggers detect a 64-bit
inferior instead of i386; correct the single-step TF comment.
- execve.rs: every ptrace tracee stops with SIGTRAP on execve (PTRACE_O_TRACEEXEC
only controls the event payload, not whether the stop occurs).
- proc.rs: drop a duplicate /proc/<pid>/mem entry in the thread dir listing.
* test(starry): convert test-gdb-native-batch to a raw-ptrace tracer
Replace the real /usr/bin/gdb driver with a self-contained raw-ptrace tracer
(matching riscv's test-ptrace-gdb), validating the kernel's ptrace on a
dynamically-linked process across execve and ld-musl startup without depending
on GDB's startup probes or target-description negotiation:
fork + PTRACE_TRACEME + execve(dynamic target) -> exec-stop -> read AT_ENTRY
from /proc/<pid>/auxv -> plant INT3 at AT_ENTRY -> PTRACE_CONT (ld-musl runs
fully under ptrace) -> trap at the application entry -> restore + single-step
-> PTRACE_CONT to exit 0.
- add c/src/tracer.c; CMakeLists builds both the dynamic target and the tracer
- qemu-x86_64.toml runs the tracer; success "DONE: N pass, 0 fail"
- remove gdb-native-batch.gdb, run-gdb-native-batch.sh, prebuild.sh (no gdb)
* test(starry): migrate x86 ptrace/gdb cases into grouped system and fix exec-stop path
Move 5 x86 ptrace/gdb test cases from undiscovered normal/qemu-smp1/ to
qemu-smp1/system/ with arch-filtered CMakeLists that install into
starry-test-suit, making them participate in the grouped CI runner.
- test-ptrace-x86-regs: remove canary fork, return exit code directly
- test-ptrace-x86-breakpoint: fix printf format string
- test-gdb-native-batch: split into tracer (starry-test-suit) and
target (usr/bin), rename to test-gdb-native-batch-tracer
Promote test-ptrace-exec-stop from starry-known-fail / riscv-only to
starry-test-suit on riscv64|x86_64. Fix hardcoded path by using
/proc/self/exe so the re-exec child finds itself under the grouped
install location.
Delete stray test-ptrace-exec-stop/qemu-x86_64.toml (double discovery).
Verified: x86_64 and riscv64 grouped system both PASS, all ptrace
binaries show STARRY_SYSTEM_TEST_PASSED.
* chore(ci): re-trigger CI after roc-rk3568 board u-boot flake
* ci: trigger test run
* ci: trigger test run
* chore: remove accidentally committed internal ptrace/gdb reports
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(axbuild): tolerate slow guests in host HTTP test server
The apk-curl-equivalence system case downloads a 20MB payload from the
host HTTP server. The server used a 1s per-write timeout and silently
discarded write errors, so whenever a slow guest (notably x86_64, the
slowest QEMU guest) applied TCP backpressure for over a second, the body
write timed out, the error was dropped, and the connection was closed
mid-stream. curl then failed with "(18) end of response with N bytes
missing", flaking the x86_64 starry qemu test.
Raise the body write timeout to 30s (still finite so a wedged guest
cannot block the server thread and its Drop/join forever) and surface
write errors instead of swallowing them.
* test(starry): wire x86 ptrace/gdb cases into grouped system runner
The new x86_64 ptrace/gdb system cases were laid out as
system/<case>/c/CMakeLists.txt + c/src/, but the qemu-smp*/system
grouped runner builds one root CMake project that only add_subdirectory()
each subcase whose CMakeLists.txt sits directly under system/<case>.
As a result these cases were never built/installed in aggregate runs and
`-c qemu-smp1/system/<case>` failed at configure time with
"unknown grouped C subcase".
Move each case to the flat system subcase layout required by
test-suit/starryos/GUIDE.md (CMakeLists.txt + src/ at the case root) and
fix the relative include of common/starry_arch_filter.cmake accordingly.
Install destinations are unchanged.
Cases: test-ptrace-x86-regs, test-ptrace-x86-breakpoint,
test-ptrace-x86-breakpoint-reinsert, test-ptrace-x86-singlestep,
test-gdb-native-batch.
* fix(starry-kernel): rebase x86_64 ptrace onto upstream/dev per-tid baseline
Replace ptrace.rs with upstream/dev version as baseline and port x86_64 code:
- Add X8664UserRegs struct + From<UserContext>/write_to/sanitize_eflags
- Add X86_64_USER_* constants + peeksuser/pokeuser/user_area_x86_64
- Add x86_64 getregs/setregs/getfpregs/setfpregs/getregset/setregset impls
- Add ptrace_setup_singlestep for x86_64 (RFLAGS.TF)
- Wire x86_64 into multi-arch dispatch gates (NT_FPREGSET/NT_PRSTATUS)
- Define x86_64 PtraceStopFpData as tuple struct + real fxsave/fxrstor
- Add x86_64 to signal.rs ptrace FP save and mod.rs save/restore
Fixes three build-blocking issues:
- ptrace_restore_singlestep_insn present for all archs (from upstream baseline)
- ptrace_setup_singlestep present for aarch64/loongarch64 (from upstream baseline)
- x86_64 FP type matches between ptrace.rs and mod.rs (tuple struct)
* fix(starry-kernel): store full FxsaveArea in x86_64 PtraceStopFpData
Replace PtraceStopFpData([u64; 32], usize) with PtraceStopFpData(FxsaveArea)
to match the 512-byte FXSAVE area. Fixes out-of-bounds memory access at
4 call sites where from_raw_parts(ptr, 512) was created from a 256-byte
[u64; 32] array — UB when the slice exceeded the allocation.
save/restore/GETFPREGS/SETFPREGS/NT_FPREGSET now directly copy the full
FxsaveArea, preserving all XMM/MXCSR state.
* fix(starry): downgrade loader/execve logs to debug, restore kernel #DB panic, add TLS contiguity comment
* test(starry): add x86_64 ptrace FP register coverage
Exercises PTRACE_GETFPREGS/SETFPREGS and NT_PRFPREG round-trip on x86_64,
checking xmm0, xmm10 (offset 320) and xmm15 (offset 400) so a regression that
preserves only part of the 512-byte FXSAVE area is caught. The child loads
known XMM values and stops via a direct kill() syscall to avoid libc clobbering
the registers; the tracer verifies the read-back, writes sentinels, and the
child confirms them after resume. Auto-discovered under qemu-smp1/system.
* fix(starry-kernel): remove duplicate ptrace_setregset_prstatus, fix axnet typo and register call
* chore: fmt execve.rs register call
* fix(starry-kernel): remove unused VirtAddr and DirectRwFsFileOps imports in proc.rs
* chore: fmt proc.rs import line
* fix(starry-kernel): gate format_statm/format_status_vm_lines with cfg(test)
* fix(starry-kernel): gate alloc::format import with cfg(test)
* chore: reorder stats.rs imports for fmt
* fix(starry-kernel): scope ptrace get/setfpregs cfg to all non-x86 arches
ptrace_getfpregs/ptrace_setfpregs use the generic ArchFpRegs path for the
non-x86 architectures, but the supported arm was gated on
any(riscv64, loongarch64) (missing aarch64) while the Unsupported fallback
was gated on not(any(riscv64, x86_64)). On loongarch64 both arms matched,
causing E0428 (duplicate definition); on aarch64 the function fell through
to the Unsupported stub instead of the real ArchFpRegs path. Widen the
supported arm to any(riscv64, aarch64, loongarch64) and the fallback to
not(any(riscv64, aarch64, loongarch64, x86_64)), matching get/setregs.
* fix(starry-kernel): restore /proc features dropped by a bad merge revert
During an earlier conflict resolution, pseudofs/proc.rs was reverted to a
pre-refactor version, silently dropping upstream features: /proc/<pid>/mem
(ProcMemFile + read_at/write_at/check_access), /proc/<pid>/status memory
stats (sample_mem_stats, TaskStatusBase/TaskStatusFields) and the namespace
directory (NsDir), plus their tests. Restore the current upstream/dev proc.rs
and re-apply the only two genuine branch-local tweaks on top: the extended
loongarch /proc/cpuinfo Feat flags, and /proc/<pid>/maps full-width addresses
with anonymous-mapping file_info tolerance.
* fix(axbuild): restore upstream overlay symlink injection
An earlier divergence replaced the two-pass overlay debugfs injection with a
single-pass variant, dropping two upstream behaviours: deferring symlink
creation until after their targets are written (debugfs validates the target),
and converting relative symlink targets to absolute guest paths. Restore the
upstream/dev implementation (which already uses link-path-first symlink args).
* fix(starry-kernel): un-gate ProcessMemStats format methods for /proc
format_statm and format_status_vm_lines had been marked #[cfg(test)] back when
the reverted proc.rs no longer called them (to avoid dead_code under -D warnings).
The restored proc.rs uses both in the real build (/proc/<pid>/statm and
/proc/<pid>/status), so the test-only gating broke non-x86 builds with E0599.
Restore upstream/dev stats.rs so the methods are available in all builds.
* chore: remove accidentally committed GitHub page snapshot
A 172KB GitHub page snapshot (Feat_x86 64 ptrace clean ... rcore-os_tgoskits@f4d00dd.html)
was swept into the branch by a stray 'git add .'. It is not source/test asset and
makes 'git diff --check' fail on trailing whitespace/EOF blank lines. Remove it and
gitignore these page snapshots so they cannot be re-committed.
* fix(starry): use STARRY_ROOTFS in gdb app prebuild
starry app qemu injects the rootfs image path as STARRY_ROOTFS, not
STARRY_BASE_ROOTFS, so the gdb prebuild failed require_env and the
GDB_SMOKE_PASSED qemu path never ran. Match the ffmpeg/pip/mosquitto apps:
read ${STARRY_ROOTFS:-${STARRY_BASE_ROOTFS:-}} and require STARRY_ROOTFS.
* refactor(starry-kernel): converge x86_64 GP registers into ArchUserRegs explicit-TID backend
- Add ArchUserRegs alias for x86_64
- Make write_to return AxResult<()> for all archs
- Expand generic read/write backends to cover x86_64
- Remove parallel x86_64 helper functions
- Unify getregs/setregs into single generic bodies
- Remove inline arch dispatch from getregset/setregset_prstatus
- Update PEEKUSER/POKEUSER user-area to generic backend
- Remove redundant selected-stop wrappers from detach_live_tracees_of
* fix(starry): use dynamic platform for gdb x86_64 app build config
The gdb app x86_64 build config pinned the legacy static x86 platform
(ax-hal/x86-pc, ax-driver/plat-static, the qemu feature, plat_dyn=false).
x86_64 Starry runs on the dynamic platform path, which registers no static
platform package, so 'cargo xtask starry app qemu -t gdb --arch x86_64'
failed at build-config with 'no default platform package is registered for
arch x86_64' and the GDB_SMOKE_PASSED path was unreachable. Drop the static
deps and match the other Starry x86_64 app configs (git/top): keep only the
virtio driver features on the dynamic platform. Verified end-to-end in the
container: boots to a shell, gdb 16.3 runs, GDB_SMOKE_PASSED.
* chore(repo): remove unused workspace crates (#1306)
* feat(axbuild): internalize Starry kallsyms flow (#1309)
* fix(ci): bump smoke-vmx QEMU timeout 180→600s for self-hosted KVM runner (#1315)
Signed-off-by: 林晨 (Leo Cheng) <chengkelfan@qq.com>
* fix(starry): correct x86_64 u_debugreg offset in struct user
x86_64 PTRACE_PEEKUSER/POKEUSER on the debug-register area used
X86_64_USER_DEBUGREG_OFFSET = 912, but u_debugreg[] sits at offset 848 in
the x86_64 `struct user` (regs 216 + u_fpvalid/pad 8 + i387 512 + tsize/
dsize/ssize 24 + start_code/start_stack 16 + signal 8 + reserved/pad 8 +
u_ar0 8 + u_fpstate 8 + magic 8 + comm 32 = 848).
gdbserver probes the hardware debug registers (DR0–DR7) via PEEKUSER at
this offset during startup; with the wrong offset it read a bogus location
and stalled before printing "Listening on port 1234", so the x86_64
gdbserver smoke hung. The native single-process GDB smoke does not touch
debug registers, which is why only the gdbserver path was affected.
Fix the offset to 848. Verified end-to-end in the container: the x86_64
gdbserver smoke now reaches GDBSERVER_SMOKE_DONE.
* feat(gdb-smoke): port GDB and gdbserver smoke to x86_64
参照现有 riscv64/aarch64/loongarch64 实现,为 gdb-smoke 增加 x86_64 的
原生 GDB 冒烟与单进程 gdbserver 冒烟移植:
- 新增 build-x86_64-unknown-none.toml 与默认 qemu-x86_64.toml(native
批量冒烟,成功标志 GDB_NATIVE_SMOKE_DONE);
- 补齐 gdbserver 全套:qemu-x86_64-gdbserver.toml(默认 gdbserver 冒烟,
GDBSERVER_SMOKE_DONE)、gdbserver-host.toml、gdbserver-manual.toml,以及
host-remote-x86_64.gdb / host-manual-x86_64.gdb(set architecture
i386:x86-64);
- prebuild.sh 的 find_qemu_runner 增加 x86_64 分支(qemu-x86_64 +
x86_64-linux-musl);
- README 补充 x86_64 native 与 gdbserver 用法。
gdbserver 路径依赖同分支的 x86_64 u_debugreg 偏移修复才能跑通。已在容器内
验证:native 冒烟 GDB_NATIVE_SMOKE_DONE、gdbserver 冒烟 GDBSERVER_SMOKE_DONE
均通过(断点/backtrace/continue/远程连接/正常退出全部正确)。
---------
Signed-off-by: 林晨 (Leo Cheng) <chengkelfan@qq.com>
Co-authored-by: 54dK3n <ken@kendeAir.lan>
Co-authored-by: 54dK3n <ken@kendeMacBook-Air.local>
Co-authored-by: 54dK3n <ken@ac-c9-06-23-1e-48.walkup.net.uq.edu.au>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: 周睿 <34859362+ZR233@users.noreply.github.com>
Co-authored-by: 禾可 <chengkelfan@qq.com>
No description provided.