__getpagesize: Assertio

Adott az alabbi program:


#include <iconv.h>
#include <stdio.h>
#include <errno.h>
int main () {
iconv_t x;
x = iconv_open ("UTF-8", "UTF-32LE");
printf ("%d\n", errno == EINVAL);
return 0;
}

$gcc -O2 -Wall -o ii ii.c
$./ii
0

so far, so good. De most jon az erdekesseg:

$gcc -O2 -Wall -static -o ii ii.c
$./ii
ii: ../sysdeps/unix/sysv/linux/getpagesize.c:32: __getpagesize: Assertion `_rtld_global_ro._dl_pagesize != 0' failed.
Aborted

A kerdes pedig: "Es akkor ezt most hogy?"

misc info:

$gcc -v
Reading specs from /usr/lib/gcc/i486-slackware-linux/4.5.2/specs
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/i486-slackware-linux/4.5.2/lto-wrapper
Target: i486-slackware-linux
Configured with: ../gcc-4.5.2/configure --prefix=/usr --libdir=/usr/lib --mandir=/usr/man --infodir=/usr/info --enable-shared --enable-bootstrap --enable-languages=ada,c,c++,fortran,java,objc,lto --enable-threads=posix --enable-checking=release --with-system-zlib --with-python-dir=/lib/python2.6/site-packages --disable-libunwind-exceptions --enable-__cxa_atexit --enable-libssp --enable-lto --with-gnu-ld --verbose --with-arch=i486 --target=i486-slackware-linux --build=i486-slackware-linux --host=i486-slackware-linux
Thread model: posix
gcc version 4.5.2 (GCC)

glibc verzio: 2.13-i486-4

Hozzászólások

gcc 4.6-tal megy. Biztos eglibc bug.


$ gcc -v
Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.4.3-4ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --program-suffix=-4.4 --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i486 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5) 

glibc: GNU C Library (Ubuntu EGLIBC 2.11.1-0ubuntu7.8) stable release version 2.11.1, by Roland McGrath et al.

staticcal forgatva 0-t ir ki.

Debian Squeeze + unstable (mindketto amd64) eredmeny ugyanez, Debian Squeeze PowerPC detto. A hiba az On keszulekeben van.

--
|8]

A hiba az On keszulekeben van.

Vegul is csak a lenyeg folott siklottal el:

gcc 4.4.4 + glibc 2.11-vel nalam sem volt ilyen problema, rendben mukodott a -static linkeles (eredmenye). Egy upgrade utan azonban gcc 4.5.2 + glibc 2.13 lett, es ezek (egyutt) mar hibas mukodest produkalnak. Btw. valoszinunek tartom amugy a glibc issue-t, mert gcc downgrade mellett is a fenti assertion hibat produkalt.

Mindenkinek kipostázzák az alkotmányt

Feltettem Debian experimentalbol 2.13-as glibct:


GNU C Library (Debian EGLIBC 2.13-0exp5) stable release version 2.13, by Roland McGrath et al.
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.4.5.
Compiled on a Linux 2.6.38 system on 2011-03-28.
Available extensions:
	crypt add-on version 2.1 by Michael Glad and others
	GNU Libidn by Simon Josefsson
	Native POSIX Threads Library by Ulrich Drepper et al
	BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.

Statikusan forgatva ugyanugy 0-t ad (hozza debian unstable-beli gcc: gcc version 4.6.1 20110428 (prerelease) (Debian 4.6.0-6)).

Egyertelmu, hogy valami libc-kornyeki hiba van, az vilagosan latszik a hibauzenetbol. Az is lehet, hogy a Debianosok mar javitottak, vagy ujabb snapshot javitotta, es nalam azert nem jon elo. Nem ez lenne az elso eset, hogy elhasal egy program, amikor statikusan linkelt letere megprobal egy .so-t benyalni (nem is igazan ertem, hogy glibcs programokat miert lehet egyatalan statikusan linkelni, amikor sok esetben ugyis ki fog hivni [iconv, nss pl], ami szvsz hazavagja a static ertelmet ahogy van).

--
|8]

Egyertelmu, hogy valami libc-kornyeki hiba van, az vilagosan latszik a hibauzenetbol.

Igen, idaig en is eljutottam. Mostmar csak egy fix vagy workaround kellene :-)

amikor statikusan linkelt letere megprobal egy .so-t benyalni

Egy statikusan linkelt program imho nem fog .so-t "benyalni"...

(nem is igazan ertem, hogy glibcs programokat miert lehet egyatalan statikusan linkelni, amikor sok esetben ugyis ki fog hivni [iconv, nss pl],

ha "ki fog hivni", akkor kell neki pl. libiconv.a, amit linkeleskor szeppen hozzacsapsz a binarishoz (azaz nem fog "kihivni").

Mindenkinek kipostázzák az alkotmányt

> Egy statikusan linkelt program imho nem fog .so-t "benyalni"...

Pedig de. Az iconv es nss, meg par egyeb dolog a glibcben pont ezt csinalja: fuggetlenul attol, hogy te static linkelted-e vagy sem, o bizony dlopenelni fogja a megfelelo .so-t. Javaslom straceld meg.


$ file ./ii
./ii: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.18, not stripped
$ strace ./ii 2>&1 | grep open | grep so
open("/usr/lib/gconv/UTF-32.so", O_RDONLY) = 3
open("/etc/ld.so.cache", O_RDONLY)      = 3
open("/lib/libc.so.6", O_RDONLY)        = 3
open("/lib/ld-linux-x86-64.so.2", O_RDONLY) = 3

Lathato, hogy libc-be is kinyulna a szentem, es az UTF-32.so-t is szepen behuzna, run-time. UTF-32.so-bol pl nincs is statikus, igy azt hiaba probalnad meg akarmilyen modon beleeroszakolni az statikus programodba, nem fog sikerulni.

A miheztartas vegett:


$ cat t2.c
#include <stdio.h>
int main (void) { printf ("Hello world!\n"); return 0; }
$ gcc t2.c -o t2 -static -O2
$ file ./t2
./t2: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.18, not stripped
$ strace ./t2 2>&1 | grep open | grep so
$

--
|8]

A glibc iconv implementációja dlopen()-re alapul. A statikusan linkelt binárisokban a dlopen() nem igazán támogatott:

all kinds of features in the libc (locale (through iconv), NSS, IDN, ...) require dynamic linking to load the appropriate external code. We have very limited support for doing this in statically linked code. But it requires that the dynamically loaded modules available at runtime must come from the same glibc version as the code linked into the application. And it is completely unsupported to dynamically load DSOs this way which are not part of glibc. [...]

Az errno-lekérdezésed egyébként szabálytalan.

Teljesen jol mukodik a static linking, amig nem hasznalsz semmit, amihez a glibc dlopenelne valamit. Mondjuk komolyabb programot nem hiszem, hogy lehetne irni, ami ne futna bele ilyenbe :P

De, ha static kell, akkor vannak alternativ libck (dietlibc, uclibc) amik tudtommal tamogatjak ezt. Glibc nem tamogatja, es ez nem Linux-specifikus, mert pl Debian GNU/kFreeBSD-n sem tamogatott (igen, ez egy kegyetlenul perverz rendszer, de letezik :P).

--
|8]

Durva hogy linuxon már ez se működik, ráadásul ha megcsinálod, ki is néznek miatta a LUG-ból ;)

Nem néznek ki érte a LUG-ból, mindenki tökéletesen tisztában van vele, hogy a statikus linkelésnek megvannak az előnyei zárt forrású programoknál. Ha valaki a lehető legtöbb tényezőt akarja az ellenőrzése alá vonni, akkor nem fog megbízni a végfelhasználó / megrendelő libc-jében, meg ld.so.conf-jában, hanem maga adja az egész miskulanciát.

De akkor miért álljunk meg itt? Ha a libc-jében nem bízik meg (teljes joggal), akkor a kernelében miért bízik meg? A hypervisor-ában miért bízik meg? A hardverében miért bízik meg?

Ezek persze költői kérdések, mert aki zárt forrású binárist terjeszt, akinek valóban fontos a teljes ellenőrzés, és azt akarja, hogy a minőségbiztosítása ne falra hányt borsó legyen, az appliance-t fog szállítani, nem statikusan linkelt binárist.

En pl. azert szeretek egy bizonyos programot statikusan linkelni, mert egy masik gepen hasznalva nem kell ott is telepiteni, stb. egy zsak lib-et.

Ehhez nem kell a programot "teljesen" statikusan linkelned, csak a kérdéses lib-eket kell a link edit phase-nek .so helyett .a-ként átadni (borzasztóan pongyolán kifejezve). Amíg a program indulásához bármi miatt kell a /lib/ld-linux.so.* (a dinamikus betöltő, avagy "ELF interpreter"), akár csak a glibc miatt is, addig az dinamikusan linkelt.

The ELF Object File Format by Dissection: the .interp section simply contains an ASCII string that is the name of the dynamic loader

Példa:


$ ldd `which nedit`
        linux-vdso.so.1 =>  (0x00007fff5ffff000)
        libXpm.so.4 => /usr/lib/libXpm.so.4 (0x00007fea76224000)
        libXext.so.6 => /usr/lib/libXext.so.6 (0x00007fea76013000)
        libXt.so.6 => /usr/lib/libXt.so.6 (0x00007fea75db2000)
        libSM.so.6 => /usr/lib/libSM.so.6 (0x00007fea75baa000)
        libICE.so.6 => /usr/lib/libICE.so.6 (0x00007fea7598f000)
        libX11.so.6 => /usr/lib/libX11.so.6 (0x00007fea75683000)
        libm.so.6 => /lib/libm.so.6 (0x00007fea75400000)
        libc.so.6 => /lib/libc.so.6 (0x00007fea750ad000)
        libXau.so.6 => /usr/lib/libXau.so.6 (0x00007fea74eab000)
        libxcb-xlib.so.0 => /usr/lib/libxcb-xlib.so.0 (0x00007fea74caa000)
        libxcb.so.1 => /usr/lib/libxcb.so.1 (0x00007fea74a8e000)
        libdl.so.2 => /lib/libdl.so.2 (0x00007fea7488a000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fea76435000)
        libXdmcp.so.6 => /usr/lib/libXdmcp.so.6 (0x00007fea74685000)

Ebben nincs libXm függőség (Motif), mert az statikusan került bele (*). Ettől a nedit még egy dynamic executable.

(*) Azért, mert a nedit kizárólag a 2.1.x-es motif-fal megy jól (x >= 30), azt pedig a disztrók már nagyon hosszú ideje nem terjesztik. LessTif meg 2.2-es sorozatú Motif van; egyik használhatatlanabb, mint a másik. Így van egy olyan dinamikus nedit-em, amit lényegében bárhova át tudok másolni önmagában, nem függök a helyi Motif-utánzattól, ugyanakkor a teljes statikus linkelés sem bánt.

A .so-k helyett a .a-kat nem muszáj kézzel belehekkelni a parancssorba, lehet használni az -l kapcsolót továbbra is, csak rendre meg kell mondani, hogy (a NEdit makefile-jából idézve):

-Wl,-Bstatic -lXm -Wl,-Bdynamic -lXp -lXpm -lXext -lXt -lSM -lICE -lX11 -lm

(A fenti függőségi listában az Xp sem szerepel, mert úgy tapasztaltam, hogy újabban azt sem szeretik használhatóan terjeszteni, így én azt is statikusan belerakattam.)

Azt persze, de ha belegondolsz, ettol a problemat nem oldod meg.
Mert mi tortenik a statikus linkeles soran? A lib maga kb. beepul a programod kodjaba, mint a program barmely .o objektuma. Innentol visszajutunk a kor elejere.
--

Ki oda vagyik, hol szall a galamb, elszalasztja a kincset itt alant. | Gentoo Portal