Freestanding 的 hex dumper,x86-64 Linux,自己写的 _start,直接用裸 syscall,链接参数是 -nostdlib -static -no-pie。编译链接都干净,没有未定义符号,但 ./hexd -v < /etc/hostname 在第一条 note() 输出之前就段错误了。
在 gdb 里看,出错位置在 hexd_main 的最开头,是一条通过 %fs 的加载,不是我写的,出错地址 0x28。别的代码都还没跑。加上 -fno-stack-protector 就正常。
我定义了我以为栈保护需要的两个符号,如下。
unsigned long __stack_chk_guard = 0x595e9fbd94fda766UL;
__attribute__((noreturn))
void __stack_chk_fail(void) { /* write to fd 2, sys_exit(134) */ }
CFLAGS = -std=c11 -O2 -Wall -Wextra -ffreestanding -fno-pic -fno-asynchronous-unwind-tables -fstack-protector-strong
guard 明明就作为普通全局变量放在那儿,为什么编译器还要去读 %fs?_start 里的栈对齐是对的,-mno-red-zone 也没变化。是不是我得自己先用 prctl 和 ARCH_SET_FS 设置好线程指针,才能调用任何东西?
从英语翻译·查看原文Freestanding hex dumper, x86-64 Linux, own _start, raw syscalls, linked with -nostdlib -static -no-pie. It builds clean with no undefined symbols, but ./hexd -v < /etc/hostname segfaults before the first note() output.
Under gdb the fault is at the very top of hexd_main, on a load through %fs that I didn't write, fault address 0x28. Nothing else has run. With -fno-stack-protector it's fine.
I defined the two symbols I thought the protector wanted:
unsigned long __stack_chk_guard = 0x595e9fbd94fda766UL;
__attribute__((noreturn))
void __stack_chk_fail(void) { /* write to fd 2, sys_exit(134) */ }
CFLAGS = -std=c11 -O2 -Wall -Wextra -ffreestanding -fno-pic -fno-asynchronous-unwind-tables -fstack-protector-strong
Why is the compiler reading %fs at all, when the guard is sitting right there as a plain global? Stack alignment in _start is right, and -mno-red-zone changed nothing. Do I have to set up the thread pointer myself, with prctl and ARCH_SET_FS, before calling anything?