- NevemTeve blogja
- A hozzászóláshoz be kell jelentkezni
Hozzászólások
Az egyszerű, mindennapos történet a következő láncolatban írható le:
User php-scriptet futtat, benne ffi-hívás egy pluginra
PHP betölti a libffi-t
libffi betölti a plugin-t
A plugin betölti (illetve hozza magával) a libglib-2.0.so-t
libglib-nek calloc kellene
A linker-loader valamilyen hibás linkelési opciók illetve a holdállás miatt nem a libc.so-ból, hanem a ld-linux-x86_64.so-ból húz elő egy calloc-ot.
Ez a spéci calloc vissza van vezetve a szintén spéci malloc-ra, amely tiszta memóriát ad vissza, tehát nem kell memset/bzero.
De a dinamikus linkelés egyik csodálatos eredményeképpen nem a spéci malloc hívódik, hanem a közönséges (a libc.so-beli).
Szóval a glib-2.0 (és talán más komponensek) működése innentől kezdve egy olyan calloc-on alapul, ami nem tiszta memóriát ad vissza. Találgathatunk, hogy mi lesz ennek az eredménye. [Szerk: Elárulom: már a libglib-2.0.so konstruktora megpusztul.]
Részletek itt:
https://www.linuxquestions.org/questions/programming-9/debugging-dlopen…
Na és hogy az AIX-on mi a pálya? Ott linkeleskor [tipikusan] nem az kerül az outputfájlba, hogy `depends on calloc` hanem az, hogy `depends on libc.a(shr64.so):calloc` illetve haladó esetben: `depends on /usr/lib/libc.a(shr64.so):calloc`.
- A hozzászóláshoz be kell jelentkezni
Ez a spéci calloc vissza van vezetve a szintén spéci malloc-ra, amely tiszta memóriát ad vissza, tehát nem kell memset/bzero.
Also 'calloc' in 'ld.linux' calls 'malloc', but doesn't call 'memset' -- guess it assumes 'malloc' returns cleared memory.
Ezt miért kellett így implementálni? A malloc()
per definition inicializálatlan memóriát ad vissza; értem én, hogy itt "spéci" malloc
-ról beszélünk, de IMHO ez akkor is bad practice, amint a végeredmény is mutatja.
- A hozzászóláshoz be kell jelentkezni
Szerintem valamilyen kompatibilitási problémát akartak orvosolni (pl i8085 alapú mikrokontrolleren nincs malloc a libc.so.6-ban (bár igaz, hogy ott egyáltalán semmilyen .so sincs)), történetesen egy újabb kompatibilitási probléma bevezetésével.
- A hozzászóláshoz be kell jelentkezni
Lehet, hogy hülye vagyok, de ha megszakadok sem értem az összefüggést: ha adott platformon nincs malloc
, akkor úgy próbálják meg a dolgot feloldani, hogy a calloc
a platformtól függetlenül szembemegy a definícióval és úgy veszi, hogy a malloc
inicializált területet ad vissza? Vagy nem jól értem?
- A hozzászóláshoz be kell jelentkezni
Hát azt én nem tudom, hogy mire gondoltak tákolás közben, de rendes lett volna tőlük, hogy ha tényleg saját memóriakezelésre volt szükség (mondjuk a legelején a betöltésnek), azt valamilyen más néven fejlesztik ki, és nem is exportálják (még Weak symbolként sem).
Viszont valaki reagált a bugreportra: https://sourceware.org/bugzilla/show_bug.cgi?id=25486
- A hozzászóláshoz be kell jelentkezni
Hát igen. Ez van, ha valaki direkt szembemegy a lefektetett konvenciókkal.
Ez a válasz, hogy "adjust the link order"? Ez még workaroundnak sem jó, hiszen ahhoz, hogy ezt valaki megtegye egy ilyen helyzetben, ahhoz az kell, hogy tudja mi történik. Te rájöttél, mert értesz hozzá, de mit kezd ezzel a helyzettel valaki, aki csak PHP-ben ügyködik és belefut ebbe a PHP->ffi->plugin->glib->bad calloc felállásba?
- A hozzászóláshoz be kell jelentkezni
Most gyónta meg a Problem Owner (agilis kifejezés;) a SO-n hogy ő Free Pascalt használ, és nem hiszi, hogy ő rakta volna bele a linkelésbe a problémát okozó dependeciát...
- A hozzászóláshoz be kell jelentkezni
Tekintve, hogy az FP nem is függ a kernelen kívül semmitől sem, így tényleg nem valószínű.
- A hozzászóláshoz be kell jelentkezni
Ennyire nem egyszerű a történet, ez egy shared lib, ami maga is számos más shared libre dependál... Az SO-ra belinkelte a kolléga a forrást, sajnos én nem tudok portugálul, és nem értek a FP-höz; ami test-et csináltam fp-2.4.6-tal, abba nem került bele ez a problémás dependencia... Bőven függhet pl. az FP-verziójától, vagy csak valaki valamit rosszul csinált...
https://stackoverflow.com/questions/59956996/problem-loading-a-library-…
http://svn.code.sf.net/p/acbr/code/trunk2/Projetos/ACBrLib/Fontes/NFe/
- A hozzászóláshoz be kell jelentkezni
Ha a lib FP-ben van írva, akkor baromi érdekes lenne, ha ilyen linkelési problémája lenne (mármint a calloc/malloc
mizéria), mert az FP saját memóriakezelést és minden egyéb a futásához szükséges cuccot statikusan fordít bele a binárisba: zéró libc függése van, nem hív se malloc
-ot, se calloc
-ot. Az más kérdés, ha valami külső lib cuccait hívogatja, de az nem része a runtime-nak; viszont memóriakezelési függvényeket minek hívogatna a libc-ből?
Lecsekkoltam az lpi-t, így hirtelen nem látok benne semmi külső függőséget, de lehet elsiklottam felette. Majd holnap leforgatom magamnál.
- A hozzászóláshoz be kell jelentkezni
A fél világ bele van húzva; ilyen a readelf kimenete [a kérdező kolléga megadta a google-drive-ján a SO-n a kérdésben]:
$ readelf -d libacbrnfe64.so
Dynamic section at offset 0xaf0c40 contains 42 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]
0x0000000000000001 (NEEDED) Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libgdk-x11-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libX11.so.6]
0x0000000000000001 (NEEDED) Shared library: [libgdk_pixbuf-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libgtk-x11-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libgobject-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libglib-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libgthread-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libgmodule-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libpango-1.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libcairo.so.2]
0x0000000000000001 (NEEDED) Shared library: [libatk-1.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libxml2.so.2]
0x0000000000000001 (NEEDED) Shared library: [libpangocairo-1.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000e (SONAME) Library soname: [libacbrnfe64.so]
Ahogy debuggoltam, a gondra a glib-2.0.so constructora szaladt rá; közben lett egy kicsit kevésbé mesterkélt példa Pascal nélkül, az is jópofa:
$ php demodule.php
demodule.init: calloc is at 0x7f29ce261b40 returned 0x1f10db0 first 8 bytes: 7f29cb90e698
- A hozzászóláshoz be kell jelentkezni
# wget http://svn.code.sf.net/p/acbr/code/trunk2/Projetos/ACBrLib/Fontes/NFe/ACBrLibNFe-change-log.txt
# wget http://svn.code.sf.net/p/acbr/code/trunk2/Projetos/ACBrLib/Fontes/NFe/ACBrLibNFe.lpi
# wget http://svn.code.sf.net/p/acbr/code/trunk2/Projetos/ACBrLib/Fontes/NFe/ACBrLibNFe.lpr
# wget http://svn.code.sf.net/p/acbr/code/trunk2/Projetos/ACBrLib/Fontes/NFe/ACBrLibNFeClass.pas
# wget http://svn.code.sf.net/p/acbr/code/trunk2/Projetos/ACBrLib/Fontes/NFe/ACBrLibNFeConfig.pas
# wget http://svn.code.sf.net/p/acbr/code/trunk2/Projetos/ACBrLib/Fontes/NFe/ACBrLibNFeConsts.pas
# wget http://svn.code.sf.net/p/acbr/code/trunk2/Projetos/ACBrLib/Fontes/NFe/ACBrLibNFeDataModule.lfm
# wget http://svn.code.sf.net/p/acbr/code/trunk2/Projetos/ACBrLib/Fontes/NFe/ACBrLibNFeDataModule.pas
# wget http://svn.code.sf.net/p/acbr/code/trunk2/Projetos/ACBrLib/Fontes/NFe/ACBrLibNFeRespostas.pas
# wget http://svn.code.sf.net/p/acbr/code/trunk2/Projetos/ACBrLib/Fontes/NFe/ACBrLibNFeStaticImport.pas
# lazbuild ACBrLibNFe.lpi
### TCodeToolManager.HandleException: [20170422130152] "include file not found "ACBr.inc"" at Line=34 Col=5 in "/root/ize/ACBrLibNFe.lpr"
Error: (lazbuild) Broken dependency: ACBr_Integrador
Hiányos a forrás, az "ACBr.inc"
fájl nincs feltöltve a többi közé, anélkül pedig nem lehet lefordítani.
Egyébként ahogy nézem a linkelt depeket, ez nem a fél világ, csak egy GTK2-es program futásához szükséges dynlibek (GTK, GDK, ATK, X11, threadek, Cairo, stb.). Amit nem értek, hogy az ld miért függőség. (A libc-t gondolom azért, mert a többi library igényli.)
program test;
begin
end.
# fpc -O3 -CX -Xs -XX test.pas
# readelf -d test
There is no dynamic section in this file.
Egy FP program alapesetben nem függ a kernelen kívül semmitől.
- A hozzászóláshoz be kell jelentkezni
Köszönöm szépen, hogy megpróbáltad; most megpróbálom másképp, de nem itt, mert már el vagyok keskenyedve.
- A hozzászóláshoz be kell jelentkezni
A hiányzó inc fájl neked nincs meg? Azt mondtad, hogy leforgattad, akkor valahonnan megvolt, nem?
Egyébként custom css-be:
.comment
{
width: 1856px !important;
}
és akkor nem keskenyedik el.
- A hozzászóláshoz be kell jelentkezni
Erre való a devops, hogy túllásson a PHP exceptionön, és belemásszon a ffi-plugin-glib-calloc láncolatba...
- A hozzászóláshoz be kell jelentkezni
Na ja. Olyan minden kis webes cégnél van. :P
- A hozzászóláshoz be kell jelentkezni
A dinamikus linkeles az ordogtol valo.
- A hozzászóláshoz be kell jelentkezni
Related: https://hup.hu/comment/1738037#comment-1738037
Ott az volt a gond, hogy linuxon a bash.exe meg a libreadline.so boldog vegyülésben élnek: ha mindkettőnek van 'setenv' nevű függvénye, akkor az nyer, akit először töltöttek be (ez rendszerint a bash.exe), annak a setenv-jét használják mind a ketten.
Aix-on meg ez messze nem szokás, mondatni sosem láttam ilyen beállítással linkelt termékez.
- A hozzászóláshoz be kell jelentkezni
AIX-en szinte minden benne van a libc-ben, itt meg minden szinten szinte minden. ;)
Valamiért az egész nem hat meg, mert php-ben láttam már néhány trehány dolgot. Eszerint belül is az. Mi lenne, ha még programoznék is benne? ;)
- A hozzászóláshoz be kell jelentkezni
> AIX-en szinte minden benne van a libc-ben
Az biza benne van.
- A hozzászóláshoz be kell jelentkezni
Valamit látni vélek a fpc-3.0.4 forrásában, ami összefügghet a problémával; elsősorban most láncot építek a verziókból, hogy hátha a 2.6.4-ről eljutok oda valamiféleképpen. Egyelőre 2.6.4 nem viszi a 3.0.2-t, folyt köv.
480 { Write sharedlibraries like -l, also add the needed dynamic linker
481 here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
482 if (isdll) then
483 begin
484 Add('INPUT(');
485 Add(info.DynamicLinker);
486 Add(')');
487 end;
Szerk:
20200203.1143: most fordul a 3.0.0
20200203.1156: lement, de valami jószándékú segítő komponens még van itt valahol:
$ ls -l /usr/local/bin/fpc
-rwxr-xr-x 1 root root 430560 Feb 3 11:44 /usr/local/bin/fpc
$ /usr/local/bin/fpc -v
Free Pascal Compiler version 2.6.4+dfsg-4 [2014/10/14] for x86_64
20200203.1205: Sikeresen telepítette a komponenseket (pl. ppcx64) a /usr/local/lib/fpc/3.0.0 könyvtárba. Csak nem ott keresi őket a fpc.exe ... Persze aki harminc éve van az iparban, az már nem lepődik meg egy kis bénázáson;)
20200203.1211: No, már a 3.0.0 is mutatja a hibát. Source
LIBRARY paslib;
USES initc;
FUNCTION g_malloc (len: longint): PChar; external 'libglib-2.0.so';
FUNCTION dlopen (filename: PChar; flags: integer): PChar; external 'libdl.so';
FUNCTION xmlAddChildList (fake: PChar): PChar; external 'libxml2.so';
PROCEDURE _init;
BEGIN
WriteLn ('Hello from Pascal');
END;
FUNCTION fun1 (a, b: integer): integer;
BEGIN
fun1 := a + b;
END;
EXPORTS
fun1;
END.
fordítás:
$ fpc -g paslib.pas
Free Pascal Compiler version 3.0.0 [2020/02/03] for x86_64
Copyright (c) 1993-2015 by Florian Klaempfl and others
Target OS: Linux for x86-64
Compiling paslib.pas
Linking libpaslib.so
hiba bemutatása:
$ readelf -d libpaslib.so
Dynamic section at offset 0x2b018 contains 29 entries:
Tag Type Name/Value
0x0000000000000001 (NEEDED) Shared library: [ld-linux-x86-64.so.2]
0x0000000000000001 (NEEDED) Shared library: [libglib-2.0.so.0]
0x0000000000000001 (NEEDED) Shared library: [libdl.so.2]
0x0000000000000001 (NEEDED) Shared library: [libxml2.so.2]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000e (SONAME) Library soname: [libpaslib.so]
Szóval két kishibás program (fpc és ld-linux) így találkozott össze szerencsésen.
- A hozzászóláshoz be kell jelentkezni
Az fpc 2.6.4 tényleg nem csinálja. Összehasonlítottam a két fpc.cfg
-t, de semmi érdemlegeset nem találtam. Talán valamelyik újabb forrás/unit is csinálhatja, vagy tényleg a compiler. (A compiler flagek közt nincs, ami ezt szabályozná.) Jelented az FPC fejlesztőknek?
Egyébként, ha a függvénydeklarációkat és az initc
unit behívását ki is szeded, az ld akkor is függőség marad. Minden más repül, de az marad.
- A hozzászóláshoz be kell jelentkezni
Jaja, föntebb idéztem is a source-ból... https://hup.hu/comment/2434556#comment-2434556
Megnézem majd, talán van valamilyen verziókövető szoftverük, amiben meg lehetne találni, hogy miért tették ezt bele.
- A hozzászóláshoz be kell jelentkezni
A verziókövetőjük itt van: https://www.freepascal.org/docs-html/current/user/userse73.html
Szerintem itt ez az érintett revízió: svn log ./compiler/systems/t_linux.pas
r19036 | tom_at_work | 2011-09-08 23:17:35 +0200 (cs, 08 szept 2011) | 27 lines
Fix shared library loading and unloading for Linux platforms. Shared library initialization and finalization are now called correctly at program startup for compile-time linked dynamic libraries on powerpc-/powerpc64-/arm-/i386- and x86_64-linux.
...
svn cat -r 19036 ./compiler/systems/t_linux.pas > t_linux.pas.r19036
svn cat -r 17889 ./compiler/systems/t_linux.pas > t_linux.pas.r17889
diff -U 3 -dHrN -- t_linux.pas.r17889 t_linux.pas.r19036
--- t_linux.pas.r17889 2020-02-03 15:48:19.279515276 +0100
+++ t_linux.pas.r19036 2020-02-03 15:47:58.047515352 +0100
@@ -330,6 +330,7 @@
s,s1,s2 : TCmdStr;
found1,
found2 : boolean;
+ linksToSharedLibFiles : boolean;
begin
result:=False;
{ set special options for some targets }
@@ -432,6 +433,13 @@
{ Write sharedlibraries like -l, also add the needed dynamic linker
here to be sure that it gets linked this is needed for glibc2 systems (PFV) }
+ if (isdll) then
+ begin
+ Add('INPUT(');
+ Add(info.DynamicLinker);
+ Add(')');
+ end;
+ linksToSharedLibFiles := not SharedLibFiles.Empty;
if not SharedLibFiles.Empty then
begin
@@ -497,8 +505,13 @@
end;
end;
- {Entry point.}
- add('ENTRY(_start)');
+ {Entry point. Only needed for executables, set on the linker command line for
+ shared libraries. }
+ if (not isdll) then
+ if (linksToSharedLibFiles and not linklibc) then
+ add('ENTRY(_dynamic_start)')
+ else
+ add('ENTRY(_start)');
{$ifdef x86_64}
{$define LINKERSCRIPT_INCLUDED}
@@ -641,7 +654,6 @@
add('OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm",');
add(' "elf32-littlearm")');
add('OUTPUT_ARCH(arm)');
- add('ENTRY(_start)');
add('SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");');
add('SECTIONS');
add('{');
Csak az az érdekes, hogy ez egy 2011-es commit, a 2.6.0 pedig 2012-es...de lehet, hogy addigra már feature freeze volt a 2.5-dev ágban, ez pedig a 2.7-dev ágban keletkezett.
- A hozzászóláshoz be kell jelentkezni