无法从可执行文件共享库中的printf浮点数 [英] Unable to printf floating point numbers from executable shared library
问题描述
我正在开发可独立执行的共享库来打印它自己的版本号。
I'm developing a shared library which can be executed independently to print it's own version number.
我已经定义了一个自定义的入口点为:
I've defined a custom entry point as:
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
这code 编译和运行完美。
This code compiles and runs perfectly.
我的问题是,当我改变的printf的参数是float或double(%F或%LF)。然后该库将编译,但段错误运行时。
My issue is when I change the parameter of the printf to be a float or double (%f or %lf). The library will then compile but segfault when run.
任何人有什么想法?
EDIT1:的
edit1:
下面是code,它出现segfaults:
Here is the code that segfaults:
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:的
edit2:
其他环保细节:
uname -a
Linux的mjolnir.site 3.1.10-1.16桌面#1 SMP preEMPT周三6月27日五时21分40秒UTC 2012(d016078)的x86_64 x86_64的x86_64的GNU / Linux的
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
海湾合作委员会(的SUSE Linux)4.6.2
gcc (SUSE Linux) 4.6.2
/lib64/libc.so.6
配置为x86_64的 - SUSE Linux的。
由GNU CC版本4.6.2编译。
编译一个Linux 3.1.0系统上2012-03-30。
Configured for x86_64-suse-linux. Compiled by GNU CC version 4.6.2. Compiled on a Linux 3.1.0 system on 2012-03-30.
的 修改3:的
edit 3:
输出在/ var /日志/后段错误消息:
Output in /var/log/messages upon segfault:
08月11日8时27分四十五秒雷神锤内核:[10560.068741] liblist.so [11222]一般保护知识产权:7fc2b3cb2314 SP:7fff4f5c7de8错误:0 libc-2.14.1.so [7fc2b3c63000 + 187000]
Aug 11 08:27:45 mjolnir kernel: [10560.068741] liblist.so[11222] general protection ip:7fc2b3cb2314 sp:7fff4f5c7de8 error:0 in libc-2.14.1.so[7fc2b3c63000+187000]
推荐答案
想通了。 :)
在x86_64的浮点运算使用XMM矢量寄存器。访问这些必须16byte边界对齐。这就解释了为什么32位平台未受影响和整数和字符的打印工作。
The floating point operations on x86_64 use the xmm vector registers. Access to these must be aligned on 16byte boundaries. This explains why 32bit platforms were unaffected and integer and character printing worked.
我编我的code装配有:
I've compiled my code to assembly with:
gcc -W list.c -o list.S -shared -Wl,-e,my_main -S -fPIC
再改变了my_main功能将有更多的堆栈空间。
then altered the "my_main" function to be have more stack space.
之前:
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文件:
Then I compiled this .S file by:
gcc list.S -o liblist.so -Wl,-e,my_main -shared
这解决了问题,但我会这个线程转发到GCC和glibc的邮件列表,因为它看起来像一个bug。
This fixes the issue, but I will forward this thread to the GCC and GLIBC mailing lists, as it looks like a bug.
EDIT1:
据的 noshadow 的海合会IRC,这是做一个非标准的方式。他说,如果一个是使用gcc -e选项,手动初始化C运行时,或者不使用libc函数。说得通。
According to noshadow in gcc irc, this is a non standard way to do this. He said if one is to use gcc -e option, either initialize the C runtime manually, or don't use libc functions. Makes sense.
这篇关于无法从可执行文件共享库中的printf浮点数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!