无法从可执行共享库中打印浮点数

时间:2012-08-11 06:11:57

标签: c linux gcc shared-libraries

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

我已将自定义入口点定义为:

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

为x86_64-suse-linux配置。 由GNU CC版本4.6.2编译。 在2012-03-30上在Linux 3.1.0系统上编译。

编辑3:

在segfault上输出/ var / log / messages:

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

1 个答案:

答案 0 :(得分:5)

想出来。 :)

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:

根据gcc irc中的 noshadow ,这是一种非标准的方法。他说如果要使用gcc -e选项,要么手动初始化C运行时,要么不使用libc函数。说得通。