2014-10-07 57 views
10

我認爲最近發生了一些變化。GnuCOBOL未能找到動態符號,僅在最近的Ubuntu上

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" 

二進制具有NO指示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,同一版本的編譯器(內置略有不同,尋找ncursesw而不是ncurses的 - 假設這是手頭沒有問題的一部分)

$ 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) 

生成的C代碼在Ubuntu

/* 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; 
0(GnuCOBOL採用C中間體)

當從C調用gtk_init時,我在Ubuntu上獲得了良好的結果(完整的ELF鏈接提示),而不是作爲傳遞給cob_resolve的字符串。使用gcc測試-o simple simple-gtk.c -lgtk-3

那麼圍繞-llibname的假設會發生什麼變化?它似乎並沒有包含在ELF數據中,因爲dlopen甚至懶得試圖尋找libgtk-3.so

更多信息: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更改哪些假設的提示。

開放式cobol軟件包在Debian和Ubuntu軟件庫上工作了好幾年了。甚至在Ubuntu上的舊版本的GnuCOBOL(GNU Cobol,或OpenCOBOL)現在都失敗了。一些東西改變了,我們沒有得到備忘錄。不止是願意更改編譯器源代碼,而是首先尋找友好的StackOverflow洞察。

這似乎不是一個本地環境問題,因爲這個Ubuntu問題也向其他人展示。這也感覺就像那些DOH中的一個!很容易解決問題。

更願意增加更多的編譯日誌,LD_DEBUG =所有場,或straces等更多

回答

5

這看起來是一個變化的編譯器驅動程序進行了Ubuntu的 - 它的代碼發送到時添加--as-needed選項編譯行collect2 aka鏈接器。

要了解發生了什麼,我們需要拆開COBC的執行更超過電子錢包正在顯示它:

cobc -x -v simple.cob -lgtk-3 
preprocessing simple.cob into /tmp/cob2743_0.cob 
translating /tmp/cob2743_0.cob into /tmp/cob2743_0.c 
gcc -pipe -c -Wno-unused -fsigned-char -Wno-pointer-sign -o /tmp/cob2743_0.o /tmp/cob2743_0.c 
gcc -pipe -Wl,--export-dynamic -o simple /tmp/cob2743_0.o -L/usr/lib -lcob -lm -lgmp -lncurses -ldb -ldl -lgtk-3 

如果我們分解成生成C代碼,然後編譯它,我們得到:

cobc -C -x -v simple.cob 
gcc -pipe -c -Wno-unused -fsigned-char -Wno-pointer-sign -o simple.o simple.c 
gcc -pipe -Wl,--export-dynamic -o simple simple.o -L/usr/lib -lcob -lm -lgmp -lncurses -ldb -ldl -lgtk-3 

我們需要的最後一行gcc進一步分解成:

gcc -### -pipe -Wl,--export-dynamic -o simple simple.o -L/usr/lib -lcob -lm -lgmp -lncurses -ldb -ldl -lgtk-3 

這yiel DS作爲輸出:

/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 "--sysroot=/" --build-id --eh-frame-hdr -m elf_x86_64 "--hash-style=gnu" --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o simple /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. --export-dynamic simple.o -lcob -lm -lgmp -lncurses -ldb -ldl -lgtk-3 -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o 

的問題是第一--as-needed選項的存在 - 它顛覆了所有明確-l選項在命令行上 - 如果沒有什麼在.o的組成文件中找到這取決於庫,它不會鏈接庫 - 這是確切的動態加載情況。

這似乎be the case since Oneiric

這個簡單的解決方法是增加:

COB_LDFLAGS=-Wl,--no-as-needed 

你的環境,這應該可以解決鏈接問題。

+0

Petesh;謝謝。這將進入編譯器源代碼樹,希望今天。 – 2015-01-14 01:29:13

5

這似乎從輸出動態查找gtk_init C代碼不知道有關裝載共享的實際libgtk-3.so對象在運行時。

您可以使用-fstatic-call選項與cobc進行編譯。這將直接調用您的庫函數,如gtk_init,而不是通過調用dlopen/dlsym。該選項的詳細信息可以在信息頁面通過命令info opencobol發現:

隨着編譯器選項-fstatic呼叫,更高效的代碼將被 這樣產生的:

subr(X); 

請注意,此選項僅在被調用程序名稱 是文字(如CALL "subr".'). With a data name (like CALL SUBR。)時纔有效,程序仍然是動態調用的。

如果你想走動態路線,我只能建議告訴你的Cobol應用程序到底想要在運行時加載哪些動態對象。爲此,您可以在啓動應用程序之前設置環境變量COB_PRE_LOAD。有關此環境變量的信息可以在此Open Cobol documentation中找到。尤其是這樣說的:

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 
+0

謝謝邁克爾,但這不是真的在這裏玩的根本問題。 GnuCOBOL的動態鏈接功能已經運行了很長一段時間,最近纔在Ubuntu上爆發。上面的命令行在Fedora上運行良好。在Ubuntu上編譯不會在命令行提到的-l庫的ELF對象中留下任何提示。這是新的破損。 (我是你引用的FAQ的守護者)。你的回答很好,但是這裏有更多的玩法。 GnuCOBOL需要與動態庫引用一起工作,已經工作,並且在任何地方,除了最近的Ubuntu都能工作。 – 2014-11-04 16:04:58

+0

感謝您的提升。我不知道你(OP)是FAQ的守護者。我的回答並不是說我實際上已經全面更新了14.04,並且使用COB_PRE_LOAD確實有效。如果我不使用它,我會在gtk_init中出錯。我很好奇COB_PRE_LOAD是否真的爲您解決了問題,如果您嘗試實際使用它? (如果這不符合你的環境可能會有什麼不妥之處?)。 – 2014-11-04 16:25:22

+0

我很好奇它是如何工作的,因爲後期綁定似乎是(從我粗略的樣子看) - Cobol怎麼知道共享對象在運行時會被加載,除非你用COB_PRE_LOAD之類的東西告訴它 - 除非在那裏有其他環境是一些更多的靜態組件在發揮和生成的「C」有點不同 我想一個明顯的問題是這樣的。您是否在所有平臺上運行相同版本的Cobol? (即Ubuntu,Fedora等) – 2014-11-04 16:25:43