弄清楚了。 :)
x86_64 上的浮点运算使用 xmm 向量寄存器。对这些的访问必须在 16 字节边界上对齐。这解释了为什么 32 位平台不受影响并且整数和字符打印可以工作。
我已将代码编译为程序集:
gcc -W list.c -o list.S -shared -Wl,-e,my_main -S -fPIC
然后更改“my_main”函数以拥有更多堆栈空间。
Before:
my_main:
.LFB6:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %eax
movsd .LC1(%rip), %xmm0
movq %rax, %rdi
movl $1, %eax
call printf
movl $0, %edi
call _exit
.cfi_endproc
After:
my_main:
.LFB6:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
subq $8, %rsp ;;;;;;;;;;;;;;; ADDED THIS LINE
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $.LC0, %eax
movsd .LC1(%rip), %xmm0
movq %rax, %rdi
movl $1, %eax
call printf
movl $0, %edi
call _exit
.cfi_endproc
然后我编译了这个 .S 文件:
gcc list.S -o liblist.so -Wl,-e,my_main -shared
这解决了这个问题,但我会将此线程转发到 GCC 和 GLIBC 邮件列表,因为它看起来像一个错误。
edit1:
根据noshadow在 gcc irc 中,这是执行此操作的非标准方法。他说,如果要使用 gcc -e 选项,要么手动初始化 C 运行时,要么不使用 libc 函数。说得通。