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)に変更したときです。その後、ライブラリはコンパイルされますが、実行時にセグメンテーション違反が発生します。

誰かアイデアはありますか?

edit1:

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:

追加の環境の詳細:

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用に構成されています。GNUCCバージョン4.6.2によってコンパイルされます。2012-03-30にLinux3.1.0システムでコンパイルされました。

編集3:

segfault時に/var/ log / messagesに出力:

8月11日08:27:45ミョルニルカーネル:[10560.068741] liblist.so [11222]一般保護ip:7fc2b3cb2314 sp:7fff4f5c7de8 error:0 in libc-2.14.1.so [7fc2b3c63000 + 187000]

4

1 に答える 1

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メーリングリストに転送します。

edit1:

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

于 2012-08-11T09:54:23.237 に答える