无法从可执行共享库中输出浮点数

我正在开发一个可以独立执行的共享库来打印它自己的版本号。

我已经定义了一个自定义入口点:

const char my_interp[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2"; void my_main() { printf("VERSION: %d\n", 0); _exit(0); } 

和我一起编译

 gcc -o list.os -c -g -Wall -fPIC list.c gcc -o liblist.so -g -Wl,-e,my_main -shared list.os -lc 

此代码编译运行完美。

我的问题是当我将printf的参数更改为float或double(%f或%lf)时。 运行时,库将会编译但segfault

有人有主意吗?

EDIT1:

这是段错误的代码:

 const char my_interp[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2"; void my_main() { printf("VERSION: %f\n", 0.1f); _exit(0); } 

EDIT2:

额外的环境细节:

 uname -a 

Linux mjolnir.site 3.1.10-1.16-desktop#1 SMP PREEMPT Wed Jun 27 05:21:40 UTC 2012(d016078)x86_64 x86_64 x86_64 GNU / Linux

 gcc --version 

gcc(SUSE Linux)4.6.2

 /lib64/libc.so.6 

configuration为x86_64-suse-linux。 由GNU CC版本4.6.2编译。 在2012年3月30日编译在Linux 3.1.0系统上。

编辑3:

在段错误时输出在/ var / log / messages:

8月11日08:27:45 mjolnir内核:[10560.068741] liblist.so [11222]一般保护ip:7fc2b3cb2314 sp:7fff4f5c7de8错误:0在libc-2.14.1.so [7fc2b3c63000 + 187000]

Solutions Collecting From Web of "无法从可执行共享库中输出浮点数"

弄清楚了。 🙂

x86_64上的浮点操作使用xmm向量寄存器。 访问这些必须在16字节边界上对齐。 这就解释了为什么32位平台不受影响,整数和字符打印的工作。

我已经编译我的代码,以汇编:

 gcc -W list.c -o list.S -shared -Wl,-e,my_main -S -fPIC 

然后改变“my_main”函数有更多的堆栈空间。

之前:

 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 

后:

 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邮件列表,因为它看起来像一个bug。

EDIT1:

根据海湾合作委员会 irc noshadow ,这是一个非标准的方式来做到这一点。 他说如果要使用gcc -e选项,可以手动初始化C运行时,或者不要使用libc函数。 说得通。