9

最近、何かが変わったと思います。

GnuCOBOL は動的リンクに依存しており、シンボルは実行時に dlsym で検索されます。この CALL ランタイム サポート コードは、OpenCOBOL で約 7 年間使用されています。Ubuntu 14.04 では動作しなくなりましたが、Fedora 19/20 では動作します。

ldd は、-l を使用してリストされたライブラリを表示しなくなりました

たとえば、テストとして、Ubuntu 14.04.1

次の COBOL プログラム

   identification division.
   program-id. simple.

   procedure division.
   call "gtk_init" using
       by value 0
       by reference null
     returning omitted 
   end-call
   goback.
   end program simple.


$ cobc -x -v -lgtk-3 simple.cob
preprocessing simple.cob into /tmp/cob710_0.cob
parsing /tmp/cob710_0.cob (simple.cob)
Return status:  0
translating /tmp/cob710_0.cob into /tmp/cob710_0.c (simple.cob)
gcc -pipe -c -I/usr/local/include   -Wno-unused -fsigned-char -Wno-pointer-sign  -o "/tmp/cob710_0.o" "/tmp/cob710_0.c"
gcc -pipe  -Wl,--export-dynamic -o simple /tmp/cob710_0.o  -L/usr/local/lib -lcob -lm -lgmp -lncurses -ldb -ldl -l"gtk-3"

バイナリには、libgtk-3.so が混在しているという兆候はありません。

./simple
libcob: Cannot find module 'gtk_init'

$ ldd simple
    linux-vdso.so.1 =>  (0x00007fff2c9fe000)
    libcob.so.1 => /usr/local/lib/libcob.so.1 (0x00007f2549b06000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2549740000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f2549439000)
    libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f25491c5000)
    libncurses.so.5 => /lib/x86_64-linux-gnu/libncurses.so.5 (0x00007f2548fa2000)
    libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007f2548d78000)
    libdb-5.3.so => /usr/lib/x86_64-linux-gnu/libdb-5.3.so (0x00007f25489d6000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f25487d2000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f2549d56000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f25485b3000)

次に、Fedora 20、同じバージョンのコンパイラー (ncurses の代わりに ncursesw を見つける、わずかに異なるビルド - これが当面の問題の一部ではないことを前提としています)

$ cobc -x -v -lgtk-3 simple.cob
Command line:   cobc -x -v -lgtk-3 simple.cob 
Preprocessing:  simple.cob -> /tmp/cob20658_0.cob
Return status:  0
Parsing:        /tmp/cob20658_0.cob (simple.cob)
Return status:  0
Translating:    /tmp/cob20658_0.cob -> /tmp/cob20658_0.c (simple.cob)
Executing:      gcc -std=gnu99 -c -I/usr/local/include -pipe -Wno-unused
                -fsigned-char -Wno-pointer-sign -o "/tmp/cob20658_0.o"
                "/tmp/cob20658_0.c"
Return status:  0
Executing:      gcc -std=gnu99 -Wl,--export-dynamic -o "simple"
                "/tmp/cob20658_0.o" -L/usr/local/lib -lcob -lm -lgmp
                -lncursesw -ldb -ldl -l"gtk-3"
Return status:  0

$ ldd simple
    linux-vdso.so.1 =>  (0x00007fffae9cf000)
    libcob.so.4 => /usr/local/lib/libcob.so.4 (0x00007f4ff2548000)
    libm.so.6 => /lib64/libm.so.6 (0x0000003e5ae00000)
    libgmp.so.10 => /lib64/libgmp.so.10 (0x0000003e7a200000)
    libncursesw.so.5 => /lib64/libncursesw.so.5 (0x0000003e5d200000)
    libtinfo.so.5 => /lib64/libtinfo.so.5 (0x0000003e69800000)
    libdb-5.3.so => /lib64/libdb-5.3.so (0x0000003e6ac00000)
    libdl.so.2 => /lib64/libdl.so.2 (0x0000003e5b200000)
    libgtk-3.so.0 => /lib64/libgtk-3.so.0 (0x0000003e6ba00000)
    libc.so.6 => /lib64/libc.so.6 (0x0000003e5aa00000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x0000003e5b600000)
    /lib64/ld-linux-x86-64.so.2 (0x0000003e5a600000)
    libgdk-3.so.0 => /lib64/libgdk-3.so.0 (0x0000003e6a800000)
    libgmodule-2.0.so.0 => /lib64/libgmodule-2.0.so.0 (0x0000003e65600000)
    libpangocairo-1.0.so.0 => /lib64/libpangocairo-1.0.so.0 (0x0000003e75200000)
    libX11.so.6 => /lib64/libX11.so.6 (0x00007f4ff2206000)
    libXi.so.6 => /lib64/libXi.so.6 (0x0000003e62600000)
    libXfixes.so.3 => /lib64/libXfixes.so.3 (0x0000003e5fe00000)
    libcairo-gobject.so.2 => /lib64/libcairo-gobject.so.2 (0x0000003e6a400000)
    libcairo.so.2 => /lib64/libcairo.so.2 (0x0000003e71000000)
    libgdk_pixbuf-2.0.so.0 => /lib64/libgdk_pixbuf-2.0.so.0 (0x0000003e6e000000)
    libatk-1.0.so.0 => /lib64/libatk-1.0.so.0 (0x0000003e75600000)
    libatk-bridge-2.0.so.0 => /lib64/libatk-bridge-2.0.so.0 (0x0000003e6c600000)
    libpangoft2-1.0.so.0 => /lib64/libpangoft2-1.0.so.0 (0x0000003e71c00000)
    libpango-1.0.so.0 => /lib64/libpango-1.0.so.0 (0x0000003e73600000)
    libfontconfig.so.1 => /lib64/libfontconfig.so.1 (0x0000003e61600000)
    libgio-2.0.so.0 => /lib64/libgio-2.0.so.0 (0x0000003e66600000)
    libgobject-2.0.so.0 => /lib64/libgobject-2.0.so.0 (0x0000003e5fa00000)
    libglib-2.0.so.0 => /lib64/libglib-2.0.so.0 (0x0000003e5e600000)
    libXinerama.so.1 => /lib64/libXinerama.so.1 (0x0000003e61e00000)
    libXrandr.so.2 => /lib64/libXrandr.so.2 (0x0000003e62200000)
    libXcursor.so.1 => /lib64/libXcursor.so.1 (0x0000003e62e00000)
    libXcomposite.so.1 => /lib64/libXcomposite.so.1 (0x0000003e74e00000)
    libXdamage.so.1 => /lib64/libXdamage.so.1 (0x0000003e67e00000)
    libwayland-client.so.0 => /lib64/libwayland-client.so.0 (0x0000003e6ec00000)
    libxkbcommon.so.0 => /lib64/libxkbcommon.so.0 (0x0000003e6b000000)
    libwayland-cursor.so.0 => /lib64/libwayland-cursor.so.0 (0x0000003e69c00000)
    libXext.so.6 => /lib64/libXext.so.6 (0x0000003e5ea00000)
    librt.so.1 => /lib64/librt.so.1 (0x0000003e5ce00000)
    libgthread-2.0.so.0 => /lib64/libgthread-2.0.so.0 (0x0000003e61a00000)
    libharfbuzz.so.0 => /lib64/libharfbuzz.so.0 (0x0000003e6f000000)
    libfreetype.so.6 => /lib64/libfreetype.so.6 (0x0000003e60e00000)
    libxcb.so.1 => /lib64/libxcb.so.1 (0x0000003e5da00000)
    libpixman-1.so.0 => /lib64/libpixman-1.so.0 (0x0000003e6f800000)
    libEGL.so.1 => /lib64/libEGL.so.1 (0x0000003e73200000)
    libpng16.so.16 => /lib64/libpng16.so.16 (0x0000003e5f600000)
    libxcb-shm.so.0 => /lib64/libxcb-shm.so.0 (0x0000003e6e800000)
    libxcb-render.so.0 => /lib64/libxcb-render.so.0 (0x0000003e70800000)
    libXrender.so.1 => /lib64/libXrender.so.1 (0x0000003e61200000)
    libz.so.1 => /lib64/libz.so.1 (0x0000003e5ba00000)
    libGL.so.1 => /lib64/libGL.so.1 (0x0000003e68200000)
    libatspi.so.0 => /lib64/libatspi.so.0 (0x0000003e6c200000)
    libdbus-1.so.3 => /lib64/libdbus-1.so.3 (0x0000003e62a00000)
    libexpat.so.1 => /lib64/libexpat.so.1 (0x0000003e60a00000)
    libffi.so.6 => /lib64/libffi.so.6 (0x0000003e5ee00000)
    libselinux.so.1 => /lib64/libselinux.so.1 (0x0000003e5ca00000)
    libresolv.so.2 => /lib64/libresolv.so.2 (0x0000003e5e200000)
    libgraphite2.so.3 => /lib64/libgraphite2.so.3 (0x0000003e6fc00000)
    libXau.so.6 => /lib64/libXau.so.6 (0x0000003e5d600000)
    libX11-xcb.so.1 => /lib64/libX11-xcb.so.1 (0x0000003e65e00000)
    libxcb-dri2.so.0 => /lib64/libxcb-dri2.so.0 (0x0000003e67200000)
    libxcb-xfixes.so.0 => /lib64/libxcb-xfixes.so.0 (0x0000003e70400000)
    libxcb-shape.so.0 => /lib64/libxcb-shape.so.0 (0x0000003e72a00000)
    libgbm.so.1 => /lib64/libgbm.so.1 (0x0000003e70c00000)
    libudev.so.1 => /lib64/libudev.so.1 (0x0000003e63200000)
    libwayland-server.so.0 => /lib64/libwayland-server.so.0 (0x0000003e74a00000)
    libglapi.so.0 => /lib64/libglapi.so.0 (0x0000003e67600000)
    libdrm.so.2 => /lib64/libdrm.so.2 (0x0000003e67a00000)
    libxcb-glx.so.0 => /lib64/libxcb-glx.so.0 (0x0000003e66e00000)
    libXxf86vm.so.1 => /lib64/libXxf86vm.so.1 (0x0000003e66200000)
    libpcre.so.1 => /lib64/libpcre.so.1 (0x0000003e5c600000)
    liblzma.so.5 => /lib64/liblzma.so.5 (0x0000003e5c200000)
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x0000003e5be00000)

Ubuntu で生成された C コード (GnuCOBOL は C 中間体を使用)

/* Line: 4         : CALL               : simple.cob */
cob_procedure_params[0] = (cob_field *)&c_1;
cob_procedure_params[1] = NULL;
cob_glob_ptr->cob_call_params = 2;
if (unlikely(call_gtk_init.funcvoid == NULL)) {
  call_gtk_init.funcvoid = cob_resolve_cobol ("gtk_init", 0, 1);
}
call_gtk_init.funcnull ((cob_s32_t)0LL, NULL);
b_1 = 0;

そしてFedora

/* Line: 4         : CALL               : simple.cob */
cob_procedure_params[0] = (cob_field *)&c_1;
cob_procedure_params[1] = NULL;
cob_glob_ptr->cob_call_params = 2;
if (unlikely(call_gtk_init.funcvoid == NULL)) {
  call_gtk_init.funcvoid = cob_resolve_cobol ("gtk_init", 0, 1);
}
call_gtk_init.funcnull ((cob_s32_t)0LL, NULL);
b_1 = 0;

gtk_init が cob_resolve に渡される文字列としてではなく、C から呼び出されると、Ubuntu (完全な ELF リンケージ ヒント) で良い結果が得られます。gcc -o simple simple-gtk.c -lgtk-3 でテスト済み

では、-llibname を取り巻く前提で何が変わったのでしょうか? わざわざ libgtk-3.so を探しても dlopen の ELF データには含まれていないようです。

詳細情報: Ubuntu で誤ったコンパイル行があると、これが機能しているように見えます。(スペルミスgtk)

$ cobc -x -v -lgkt-3 simple.cob
Command line:   cobc -x -v -lgkt-3 simple.cob 
Preprocessing:  simple.cob -> /tmp/cob13556_0.cob
Return status:  0
Parsing:        /tmp/cob13556_0.cob (simple.cob)  
Return status:  0
Translating:    /tmp/cob13556_0.cob -> /tmp/cob13556_0.c (simple.cob)
Executing:      gcc -std=gnu99 -c -I/usr/local/include -pipe -Wno-unused
                -fsigned-char -Wno-pointer-sign -o "/tmp/cob13556_0.o"
                "/tmp/cob13556_0.c"
Return status:  0
Executing:      gcc -std=gnu99 -Wl,--export-dynamic -o "simple"
                "/tmp/cob13556_0.o" -L/usr/local/lib -lcob -lm -lgmp -lncurses
                -ldb -ldl -l"gkt-3"
/usr/bin/ld: cannot find -lgkt-3
collect2: error: ld returned 1 exit status
Return status:  256

それでも、正しいコンパイル行では、ELF は gtk-3 へのリンケージのヒントを示していません。

私はこれについてしばらくの間、頭を悩ませてきました。Ubuntu と gcc および/または ld および/または dlopen dlsym でどのような仮定が変更されたかについてのヒントを探しています。

open-cobol パッケージは、Debian および Ubuntu のリポジトリで数年前から機能しています。Ubuntu 上の GnuCOBOL (GNU Cobol または OpenCOBOL) の古いバージョンでさえ、すべて失敗します。何かが変わって、メモを取得できませんでした。コンパイラのソースを変更したいと思っていますが、最初にフレンドリーな StackOverflow の洞察を探しています。

この Ubuntu の問題は他の環境でも発生しているため、これはローカル環境の問題ではないようです。これも DOH の 1 つのように感じます。問題を簡単に修正できます。

コンパイル ログ、LD_DEBUG=all ダンプ、または strace などを追加したいと思っています。

4

2 に答える 2

5

出力から、動的に検索する C コードは、実行時に実際の共有オブジェクトをgtk_initロードすることを認識していないように見えます。libgtk-3.so

オプションを使用して cobc でコンパイルでき-fstatic-callます。gtk_initこれにより、 dlopen/dlsym への呼び出しではなく、ライブラリ関数が直接呼び出されます。このオプションの詳細については、次のコマンドを使用して情報ページを参照してくださいinfo opencobol

コンパイラ オプション-fstatic-callを使用すると、より効率的なコードが次のように生成されます。

subr(X);

このオプションは、呼び出されたプログラム名がリテラル ( CALL "subr".'). With a data name (likeCALL SUBR.' など) の場合にのみ有効であり、プログラムは引き続き動的に呼び出されることに注意してください。

動的ルートに進みたい場合は、実行時にどの動的オブジェクトをロードするかを COBOL アプリケーションに正確に伝えることをお勧めします。これを行うにはCOB_PRE_LOAD、アプリケーションを起動する前に環境変数を設定できます。この環境変数に関する情報は、この Open Cobolドキュメントにあります。特に、次のように述べています。

COB_PRE_LOADは、実行に含まれるダイナミック リンク モジュールを制御する環境変数です。

$ cobc occurl.c
$ cobc occgi.c
$ cobc -x myprog.cob
$ export COB_PRE_LOAD=occurl:occgi
$ ./myprog

これにより、OpenCOBOL ランタイム リンク リゾルバーは、occurl.so モジュールで CALL「CBL_OC_CURL_INIT」のエントリ ポイントを見つけることができます。注: COB_PRE_LOAD 環境変数にリストされているモジュールには拡張機能がありません。OpenCOBOL は、さまざまなプラットフォームで正しいことを行います。

いくつかの方法で実行できます ( を使用bash):

COB_PRE_LOAD=libgtk-3 ./simple

これによりCOB_PRE_LOAD、使用するように設定されlibgtk-3.so(オフのまま.so)、アプリケーションが起動され、終了すると元の状態にリセットさCOB_PRE_LOADれます。export以下を使用して、セッション中に環境変数を設定することもできます。

export COB_PRE_LOAD=libgtk-3 
./simple

COB_PRE_LOADそれぞれをコロンで区切ることにより、複数の共有オブジェクトを指定できます。したがって、必要に応じlibgtk-3libgmp、たとえば、次のようにすることができます。

COB_PRE_LOAD=libgtk-3:libgmp ./simple
于 2014-10-28T21:40:40.913 に答える