kob*_*ien 10 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);
}
Run Code Online (Sandbox Code Playgroud)
我编译
gcc -o list.os -c -g -Wall -fPIC list.c
gcc -o liblist.so -g -Wl,-e,my_main -shared list.os -lc
Run Code Online (Sandbox Code Playgroud)
此代码编译和运行完美.
我的问题是当我将printf的参数更改为float或double(%f或%lf)时.然后该库将编译,但段错误运行时.
有人有主意吗?
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);
}
Run Code Online (Sandbox Code Playgroud)
EDIT2:
其他环境细节:
uname -a
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
gcc(SUSE Linux)4.6.2
/lib64/libc.so.6
Run Code Online (Sandbox Code Playgroud)
配置为x86_64-suse-linux.由GNU CC版本4.6.2编译.在2012-03-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]
弄清楚了.:)
x86_64上的浮点运算使用xmm向量寄存器.访问这些必须在16字节边界上对齐.这解释了为什么32位平台不受影响,整数和字符打印工作.
我已将代码编译为程序集:
gcc -W list.c -o list.S -shared -Wl,-e,my_main -S -fPIC
Run Code Online (Sandbox Code Playgroud)
然后将"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
Run Code Online (Sandbox Code Playgroud)
后:
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
Run Code Online (Sandbox Code Playgroud)
然后我编译了这个.S文件:
gcc list.S -o liblist.so -Wl,-e,my_main -shared
Run Code Online (Sandbox Code Playgroud)
这解决了这个问题,但我会将这个帖子转发给GCC和GLIBC邮件列表,因为它看起来像一个bug.
EDIT1:
根据gcc irc中的noshadow,这是一种非标准的方法.他说如果要使用gcc -e选项,要么手动初始化C运行时,要么不使用libc函数.说得通.