gcc linker egymenetes?

Fórumok

Az újabb gcc (4.6.3, ubuntu precise) linker megadott --start-group --end-group opciók ellenére egymenetesként működik. Így linkelek (script részlet a make rendszer mélyéről):


echo -Wl,--start-group >>$RSPLNK
for i in $BUILD_LIB; do echo $i >>$RSPLNK; done
echo -Wl,--end-group >>$RSPLNK

Az RSPLNK a válaszfálj neve. A --start-group --end-group opciók között felsorolódnak a linkelni kívánt könyvtárak. A válaszfájlt végül így használom:


c++ `cat $RSPLNK`

Namost ez 10 (vagy 20) évig jó volt így. Idén tavasszal, viszont azt vettem észre, hogy a linker mégis egymenetesen működik. Áthidaló megoldásként a scriptben megdupláztam a --start-group --end-group kiírását, így kétmenetes lesz. Működik, de a dolog felettébb bosszantó.

Másik eset:

A B.so hivatkozik egy A.so-ban definiált függvényre. B.so linkelésekor nincs magadva (eddig nem kellett) az A.so. A végrehajtható X program hivatkozik mind A.so-ra mind a B.so-ra. X linkelésekor megadom A.so-t is, B.so-t is. Eddig szépen működött.

Egy ideje azonban X linkelésekor az a hibaüzenet, hogy a B.so-ban feloldatlan hivatkozás marad egy A.so-beli függvényre. Ezért kénytelen vagyok már B.so-ba is belelinkelni az A.so-t.

Úgy látom, hogy itt indokolatlan funkcióvesztés van. Nem lehet számítani a dolgokra. Vélemények?

Hozzászólások

Köszönöm, ez volt a megoldás.

Nem az ld változott, hanem az ubuntu. Azt hiszem ubuntuban változtatták meg ennek az opciónak a defaultját. A debian wheezy-ben ugyanolyan változatú (2.22) ld van, mint a precise-ban, mégis a régi módon működik. Amúgy az --as-needed opció nyilvánvalóan rosszul működik, úgyhogy az egész csak szivatásra jó.
--
ulysses.co.hu

Amikor elkezdett bejönni a golden linker, akkor volt egy tonna hasonló jellegű bug(?), ami felszínre került (bocs, ha triviális).
A 4.6-os gcc már alapból preferálja a golden linkert (http://gcc.gnu.org/gcc-4.6/changes.html).
Flameeyes bloggolt elég sokat erről. Külön tag van a blog-ján a gold-hoz:
https://blog.flameeyes.eu/tag/gold
Habár azt a post-ot most hirtelen nem találom, ahol pont arról beszél, hogy mi van akkor ha A nem linkelte B-t, pedig a golden szerint kellett volna, de C linkeli A-t és B-t is. De volt valami ilyen is. Minden esetre a mostani binutils elég értelmesen kiírja, hogy mi ilyenkor a baja. Persze te nem binutils-ról, hanem gcc-ről beszélsz, tudom...
Szóval az a gyanúm, hogy nem bug, hanem feature.

Egyébként a golden az asszem nem egy GNU ragály. Felütötte a fejétt clang/llvm szinten is...
http://stackoverflow.com/questions/14954975/how-to-use-gold-for-link-ti…
Ebben nincs személyes tapasztalatom.

Az egymeneteshez nem tudok hozzászólni.

Üdv:
Dw.

"Jegyezze fel a vádhoz - utasította Metcalf őrnagy a tizedest, aki tudott gyorsírni. - Tiszteletlenül beszélt a feljebbvalójával, amikor nem pofázott közbe."

Köszönöm az infót. Fogalmam sem volt arról, hogy egyáltalán létezik a gold. Nálam mindenesetre nem az fut, hanem a GNU ld 2.22. Van ugyan egy binutils-gold csomag az ubuntu repóban, de nálam nincs installálva. Amúgy, az optimalizálásnál sokkal jobban érdekel a stabilitás és hordozhatóság. Rengeteg programot fordítok ugyanazzal a make rendszerrel Linuxon, BSD-n, Windowson, és rosszul érint, ha ilyen változások miatt megbicsaklik a hordozhatóság.

Nekem az a gyanúm, hogy a két eset összefügg. Azonkívül: Ha a 2. eset feature volna, akkor le kellene mondanunk olyan so-k készítéséről, amik keresztbe hivatkoznak egymásra, márpedig ez korábban lehetséges volt. Sőt, most is lehetséges, kipróbáltam egy mini projektben, amiben semmi más nincs csak egy ilyen kereszthivatkozás.
--
ulysses.co.hu

Tenyleg csak egy velemeny... vagyis inkabb ke'rde's:

Ezért kénytelen vagyok már B.so-ba is belelinkelni az A.so-t.

Ez pontosan miert is baj? Ha tudom, hogy B-nek szuksege lesz A-ra, akkor B-hez hozzalinkelem, en legalabbis eddig mindig igy csinaltam... Es ha majd a main()-t (X-et) forditjuk, akkor ott ma'r csak B-t kell hozzalinkelni, es akkor az `ldd` ma'r mindent jol mutat, mennek a dolgok. Szvsz ez a logikusabb sorrend.

Ugy remlik, kavarodas csak akkor volt mikor B-t dlopen()-nel huzzuk be, azaz X linkido"ben nincs semmi info errol...

Jo kerdesek. Az esetedet olyasmihez tudna'm hasonlitani, hogy mintha csak futtata'si ido"ben akarnank eldonteni, hogy egy adott funkciot/eljarast konkretan melyik lib is implemental. Pelda: me'g anno a gtk1.2/gtk2.0 atmenet tajekan byte-rol byte-ra ugyanazt a C kodot le lehetett forditatni -lgtk opcioval ill -lgtk2.0-val is (ill ugyanennek a pkg-config --libs megfelelojevel). Ahogy igy most atjon, olyasmi lenne a szerinted "nem logikus"-nak megfelelo opcio, hogy csak futtata'skor dontenem el hogy a gtk_random_funct() az most a gtk1-bol vagy gtk2-bol jon. Szoval en nem akarom megadni az X (main) linkele'sekor hogy mi kell, hanem "majd". Hogy (X) -> gtk szinten adom ezt elo" vagy (X -> B) -> A szinten, az kabe mindegy is...

Viszont, ha futtatasi idoben akarunk vmit eldonteni, akkor arra ott a dlopen(), dlsym() et al., szoval jo kerdes, hogy akkor most mi is a logikus. Igy roviden:

  • ha forditasi/linkele'si idoben tudom mit akarok, akkor -lA, -lrandom, mindent megadhatunk, es adjunk is meg.
  • ha nem, akkor ott a dlopen().

Akkor még egyszer. Nem arról van szó, hogy nem tudom összelinkelni a programomat. Az első posztban írtam, hogy már tavasszal észrevettem az eltérést, csak eddig együtt éltem vele. Most viszont van időm vizsgálódni, hogy mi a helyzet.

Az ld időnként egymenetesen működik. Feloldatlan hivatkozások maradnak. Ha csak annyit változtatok, hogy a könyvtárak felsorolását megduplázom (két menet), akkor megjavul.

Időnként nem old fel olyan hivatkozásokat, amikhez pedig meg van adva a könyvtár. Ha máshol (a linkelt so-k linkelésekor, elvileg feleslegesen) is megadom ugyanazt a könyvtárat, akkor megjavul.

Nem érdekelnek az olyan válaszok, amik azt magyarázzák, hogy valójában miért is éppen a hibás működés a jó.

Ezeken a rendszereken nem jelentkezik a hiba:

FreeBSD 8.2 64bit, ld 2.14 (2004.05.23)
intrepid 32bit, ld 2.18.93 (2008.10.09)
lucid 32bit, ld 2.20.1 (2010.03.03)

Ezen meg jelentkezik:

precise 64bit, ld 2.22 (nem írja ki a dátumot)

Arra tippelek hogy ez okozza az eltérést (ld changelist):


Changes in 2.22:

* --copy-dt-needed-entries is no longer enabled by default.  Instead
  --no-copy-dt-needed-entries is the default.

--
ulysses.co.hu

A tényállás pontosabb rögzítése.

A termek.exe program mindenféle so-kat linkel, többek között ezeket:
xmldom.so
util.so (hivatkozik xmldom.so-ra, de nem linkeli)
tds.so (hivatkozik xmldom.so-ra, és be is linkeli)

Ha a fenti séma szerint linkelek, akkor az ld 2.22 azt mondja,
hogy util.so-ban feloldatlan hivatkozás marad xmlparserNew-ra,
ami az xmldom.so-ban van, tehát elvileg fel kéne tudni oldania.

A következő 3 változtatás bármelyike megoldja a problémát:

1) Ha az util.so linkeléséhez hozzáadom xmldom.so-t, akkor megjavul.

2) Ha a tds.so linkeléséből kiveszem xmldom.so-t, akkor megjavul.

3) Valójában a termek.exe programnak nincs szüksége a tds.so-ra.
Ha a termek.exe linkeléséből kiveszem tds.so-t, akkor is megjavul.

A --copy-dt-needed-entries opció visszaállítása nem okoz semmilyen látható eltérést. Az egymenetesség sem változik.

--
ulysses.co.hu