2012-08-11 6 views
10

独自のバージョン番号を表示するために独立して実行できる共有ライブラリを開発しています。実行可能な共有ライブラリから浮動小数点数を出力できません

私は、カスタムのエントリー・ポイント定義しました:

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:

追加環境の詳細:

012ここ

がセグメンテーション違反コードであります

Linuxは3.1.10-1.16-デスクトップ#1 SMP PREEMPT水6月27日午前五時21分40秒UTC 2012(d016078)のx86_64 x86_64のx86_64でGNU/Linuxの

gcc --version 

のgcc(SUSE Linux)のmjolnir.site 4.6.2

x86_64-suse-linux用に設定されています。 GNU CCバージョン4.6.2でコンパイルされています。 2012-03-30 Linux 3.1.0システムでコンパイルされました。

編集3:

出力中/セグメンテーション違反時にVAR/log/messagesに:

8月11日午前8時27分45秒ミョルニルカーネル:[10560.068741]一般[11222] liblist.so保護ip:7fc2b3cb2314 sp:7fff4f5c7de8エラー:0 libc-2.14.1.so [7fc2b3c63000 + 187000]

+1

これは私の32ビットマシンでは完全に機能します。 64ビットでも動作するはずです。 を含めましたか? – TOC

+1

@TOCしました。バージョン番号として浮動小数点数を印字してみましたか?フロートを印刷する場合を除いて、私が投稿したコードはうまく動作します。 – kobrien

+0

フロートを印刷するコードを表示できますか? –

答えて

5

それを実証しました。 :)

x86_64の浮動小数点演算は、xmmベクトルレジスタを使用します。これらへのアクセスは、16バイトの境界に揃えなければなりません。これは、32ビットプラットフォームが影響を受けず、整数と文字の印刷が機能する理由を説明しています。

私はアセンブリに私のコードをコンパイルした:多くのスタック領域を持っていることを「my_main」機能を変更し、その後

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

。後

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 

::前

これは、問題を修正し、私は意志

gcc list.S -o liblist.so -Wl,-e,my_main -shared 

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とGLIBCのメーリングリストはバグのようです。

EDIT1:

gccのIRCでnoshadowによると、これはこれを行うための非標準的な方法です。彼は、gcc -eオプションを使用する場合は、Cランタイムを手動で初期化するか、libc関数を使用しないことにしました。意味をなさない

+0

ISTRには、gccがデフォルト境界よりも大きな境界にスタックを揃えるオプションがあります。アセンブリを変更する代わりに、バグが修正されるまで回避することができます。 – AProgrammer

+0

いいですね。別の方法は、libc関数を使用せずにsyscallを直接使用することですが、これはコードが増えて移植性が低いことに注意してください。 – kobrien

+1

XMMレジスタに単一の浮動小数点値をロードする命令では、16バイトのアライメントは必要ありません。倍精度の場合は、単精度と8バイトのアラインメントでは、4バイトのアライメントのみが必要です。サブルーチンを呼び出すために必要なアプリケーションバイナリインターフェイス(スタックが正しく整列されていない、浮動小数点パラメータが渡されたことを示すビットを設定できなかったり、その他の問題が発生している可能性があります)に違反するなどのその他の問題が発生している可能性があります。 –

関連する問題