KDE a sdilene knihovny (Was Re: Programovani - shared libraries na Linuxu)

Pavel Kankovsky peak na argo.troja.mff.cuni.cz
Sobota Září 8 21:14:01 CEST 2001


On Wed, 5 Sep 2001, Lubos Lunak wrote:

>  Ja o XIM nevim naprosto nic, ale bez XIM v KDE programech nejdou mrtve 
> klavesy, jak uz jsem rekl. A bez mrtvych klaves se cesky pise dost spatne. 

XIM znamena X Input Method. Je obecny mechanismu, pomoci ktereho je mozno
vkladat jednotlive symboly mechanismem slozitejsim, nez je jednoduche
zmacknuti jedne klavesy (pripadne soucasne s nejakymi shifty apod.). Na
mrtve klavesy by asi stacilo neco mene obecneho, ale mejte soucit
s ubohymi Asiaty, kteri musi do pocitace vkladat ty svoje priserne
obrazky.

(Jinak nechci zpochybnovat, ze by se to dalo zestihlit. Jenom to nekdo
musi udelat. Nejlepe nekdo dost motivovany, ze? <g>)


On Wed, 5 Sep 2001, Lubos Lunak wrote:

>  Clovek se porad uci, tohle neznam. A koukam k tomu v dokumentaci kernelu 
> ani nemuzu najit dokumentaci. No, kazdopadne, pro treba tu zminovanou 
> libkdeui to vypada asi takhle :
> 
> 40245000-40248000 rw-p 000aa000 03:02 164498 libksycoca.so.3.0.0
> 40248000-40433000 r-xp 00000000 03:02 164494 libkdeui.so.3.0.0
> 40433000-4044b000 rw-p 001ea000 03:02 164494 libkdeui.so.3.0.0
> 4044b000-4044d000 rw-p 00000000 00:00 0
> 4044d000-4046f000 r-xp 00000000 03:02 164495 libkdesu.so.1.0.0

Vyznam polozek nemusi byt dokumentovan, protoze je intuitivni. :)
Prvni dve hodnoty jsou pocatek a konec v pameti (konec je adresa
nasledujici za koncem, a tudiz je velikost jejich rozdil). Druha polozka
jsou atributy (r=read, w=write, x=execute, p/s=private/shared), treti je
ofset vzhledem k zacatku tam mapovaneho souboru (je-li jaky), zbytek
je major:minor, inode a cesta k namapovanemu souboru.

> Treba odklon od pouzivani CORBA (jo jo, KDE zkouselo tuhle vec
> pouzivat jeste pred GNOME), byt ted KDE zalozene na CORBA, asi by se
> to ani do 128MB pocitace slusne neveslo.

Ovsem GNOME ji pouziva porad (AFAIK) a do 128 MB se v pohode vejde.


On Thu, 6 Sep 2001, Lubos Lunak wrote:

>  Takze, pro pripadne zajemce jsem z poznamek zatim slozil dohromady
> tohle nize o knihovnach. Predem musim jeste jednou zduraznit, ze mam o
> tehle vecech jen povrchni znalosti, vim treba, k cemu je .got, ale uz
> ne, jak to presne pracuje. Z cehoz vyplyva, ze tohle dole mohou byt
> pekne neznalkovske fantasmagorie (ale za temi cisly si stojim).

.plt a .got jsou -- ve zkratce -- sekce, kam se v PIC kodu shromazduji
adresy relokovatelnych symbolu (v .plt jsou funkce -- ve skutecnosti tam
jsou misto samotnych adres cele "stub functions", ktere lze primo volat,
v .got jsou to ukazatele na skutecne adresy globalnich promennych).

>  - Tzv. konflikty pri prelinkovani, bylo mi to vysvetleno asi takhle :
> 
> libta.so: obsahuje foo() { return 1; }
> libtb.so: obsahuje bar() { foo(); }, slinkovane s -lta
> libtc.so: obsahuje foo() { return 2; }, slinkovane s -ltb
> 
>  Kdyz se prelinkuje libtb, tak foo() je odkaz do libta, jenze kdyz se
> prelinkuje libtc, tak foo() musi byt odkaz do libtc. Takze pri spousteni
> programu slinkovaneho s libtc se tehle odkaz stejne musi relokovat, a to
> samozrejme znamena zapis a duplikaci prislusne pametove stranky.

Ano, takhle to skutecne funguje. A je to velice prakticke, protoze lze
zmenit chovani programu pomoci LD_PRELOAD, coz se leckdy hodi. Pod MS
Windows to lze udelat pouze ukrutne komplikovanym zpusobem, ktery je navic
nespolehlivy.

> Moje teorie je takova, ze gcc si obcas moc nevi rady s vecmi jako
> sablony, virtualni tabulky, inline metody a podobne a pro jistotu je v
> nekterych pripadech emituje vic nez jednou. Sice jsou jako
> LINK_ONCE_DISCARD, takze ve vysledne knihovne jsou tyhle symboly jen
> jednou, ale linker uz se neobtezuje (nebo mozna ani nemuze) podivat,
> ze tyhle symboly uz existuji v nejake knihovne, s kterou se tahle
> vysledna linkuje. Takze vsechny veci jsou pekne zduplikovane a dopadne
> to jak s tou libtc nahore.

Aaaa...asi jsme uhodili hrebicek na hlavicku. C++, your second name is
bloat. Cele je to totiz *vrozeny* defekt C++.

Zacalo to v C: jednotlive moduly jsou de facto uplne nesouvisejici kusy
zdrojoveho kodu, ktere se zcela samostatne zkompiluji a nakonec slinkuji.
Pritom veci jako definice typu (napr. struct) prestavaji po kompilaci
existovat a dokonce je mozne, ze ruzne moduly si pod stejnym jmenem
predstavuji ruzne typy (a dokonce je mozne, ze to bude ve vysledku
fungovat).

Drhnout to pochopitelne zacalo pri generovat ladicich informaci, protoze
ty musi definice typu obsahovat, ale kompilator nema tuseni, ktery
z modulu typ definuje (ve smyslu rozdilu deklarace a definice)...ony ho
totiz ve skutecnosti definuji vsechny, ktere ho pouzivaji. Takze kazdy *.o
vyrobeny ze zdrojaky pracujiciho se stdio obsahuje v ladicich informacich
kompletni definici FILE. (Tohle mozna nekterym lidem vysvetli zahadu, proc
-g zpusobi tak ukrutny narust velikosti po kompilaci.)

A ted do toho prislo C++, kde definice trid, konstant (pres const) a
inline funkci ci metod (nemluve o sablonach, ale ty pro jednoduchost
nebudu rozvadet) vede ke generovani *skutecneho* kodu a/nebo dat bez toho,
aby bylo jasne urceno, ktery modul je vlastne ten pravy (srovnejte to
napr. s moduly v jinych jazycich: Turbo Pascal, Delphi, Ada...tam vsude je
vztah kompilacnich jednotek a definic jasne urcen). Cili nezbyva nez to
vlastne vygenerovat pri *kazde* kompilaci a pak doufat, ze to linker nejak
chytre posklada dohromady. Vyskytly se take snahy (zvlaste u sablon), ze
by kompilator automaticky udrzoval umele moduly, do kterych by takove veci
ukladal, ale nebyly moc uspesne (aspon pokud vim). GNU C++ extenze #pragma
interface a #pragma implementation byly take pokus o reseni tohoto
problemu.

Nejhorsi je situace samozrejme v pripade dynamickeho linkovani, protoze
tady ten bordel musi do znacne miry uklidit az dynamicky linker. Kdyz
vyrabite dynamickou knihovnu, tak ld predem *nevi*, s cim dalsim bude
slinkovana, a tudiz musi predpokladat nejhorsi -- tj. tam nahazet vsechno,
co je potreba. Dynamic linker pak pochopitelne uvidi vicenasobne definice
tehoz a musi to nejak vyresit.

Ano, daji se asi provest urcita zlepseni: neemitovat do *.so VMT vicekrat,
emitovat je pouze kdyz dana knihovna definuje aspon jednu metodu atd. Ale
zakladni chyba je v samotnem programovacim jazyce. Smutne je, ze tvurci
jeho normy se "povznesli nad detaily" a proste strcili hlavu do pisku.

>  Kdyz tak nad tim jeste premyslim, nejde nejakou tou LD_xxx promennou 
> zjistit, presne ktere symboly zpusobuji konflikty ?

Existuje neco jako LD_TRACE a LD_TRACE_OUTPUT, coz by melo prinutit
dynamic linker k vice ci mene podrobne zprave o tom, co provadi.

>  Moje takova predstava o reseni tohohle by bylo, ze gcc pri generovani dat,
> ktere by sly v non-PIC kodu do .rodata ale v PIC musi do .data, by nesly do
> .data, ale do nejakeho nazveme ho treba .almostrodata. Tenhle .almostrodata 
> by mel stejne flagy jako .data (CONTENTS, ALLOC, LOAD, DATA, zadne 
> READONLY), ale linker by pri vytvareni knihovny posbiral .data a naskladal 
> je v knihovne za sebe, pak by posbiral .almostrodata a ty poskladal za 
> sebe. Bingo, v tehle teorii zapisy do promennych duplikuji stranky, ktere 
> obsahuji jen promenne, ale ne konstatni data. Ted jeste jak se tahle teorie 
> lisi od praxe (a to ja nevim).

To uz gcc umi, kdyz se mu to rekne explicitne:

	__attribute__ ((section ("...") ))

pak je treba jeste instruovat linker, jak to ma slinkovat, coz se udela
zmenou ld scriptu.

P.S. Dovolil bych si pozadat, aby byly dopisy citovany zpusobem, ktery
nebude u ctenaru vyvolavat dojem, ze nekdo (ja) rekl neco, co rekl nekdo
uplne jiny.

--Pavel Kankovsky aka Peak  [ Boycott Microsoft--http://www.vcnet.com/bms ]
"Resistance is futile. Open your source code and prepare for assimilation."



Další informace o konferenci Linux