无法从可执行文件共享库中的printf浮点数 [英] Unable to printf floating point numbers from executable shared library

查看:176
本文介绍了无法从可执行文件共享库中的printf浮点数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆