从零写OS(三十一):运行 musl libc 程序 —— 两个隐藏的寄存器 Bug
上一章对齐了 Linux syscall ABI,现在试着跑一个真正用 musl libc 静态编译的 C 程序。目标很简单: #include <stdio.h> int main(int argc, char **argv) { printf("hello from musl libc!\n"); printf("argc=%d\n", argc); return 0; } 编译:musl-gcc -static -O2 -o hello.elf hello.c 结果踩了两个隐藏很深的寄存器 bug,花了不少时间才找出来。 新增的 syscall musl libc 启动时会调用一批 syscall,其中有三个是绕不过的: syscall 编号 说明 arch_prctl(ARCH_SET_FS, addr) 158 设置 TLS base(FS 寄存器) set_tid_address(tidptr) 218 设置线程 ID 地址,返回 pid writev(fd, iov, iovcnt) 20 向量写,musl 的 stdio 用它输出 arch_prctl 需要写 MSR 0xC0000100(FS.base),这是 TLS 的基地址,musl 用来存放线程局部变量: case SYS_ARCH_PRCTL: if (a1 == ARCH_SET_FS) { wrmsr(0xC0000100, a2); // FS.base MSR return 0; } return (uint64_t)(-EINVAL); writev 需要遍历 iov 数组,把多段数据拼起来写到 tty: ...