AIX: linkelési hiba -- túlbuzgó collect2

Úgy tűnik nekem, hogy AIX-on a collect2 olyan konstruktorokra/destruktorokra is lecsap, amelyek ott vannak ugyan a *.a fájlban, de a konkrét executabléba nem kellenének. A példaprogram:


/* collect2_main.cc */

#include <cstdio>

int main ()
{
    fprintf (stderr, "A főprogram vagyok, semmi különös\n");
    fflush (stderr);
}

Futásának eredménye, ha csak úgy 'normálisan' linkeljük:

$ ./collect2_prob
A főprogram vagyok, semmi különös

Ha hozzálinkelünk egy másik objektet, amit nem hívunk és nem használunk ugyan, de amiben van egy globális objektum, akkor annak azért lefut a konstruktora (AIX-on és linuxon is):

$ ./collect2_prob_o
HibaProvokalo: Nekem qrvára nem kellene futnom
A főprogram vagyok, semmi különös

Ha nem az objektet adunk a linkernek, hanem egy *.a könyvtárat, és abban a 'felesleges' objektet, akkor az eredmény különböző lesz AIX-en és linuxon:

linux$ ./collect2_prob_a
A főprogram vagyok, semmi különös

AIX$ ./collect2_prob_a
HibaProvokalo: Nekem qrvára nem kellene futnom
A főprogram vagyok, semmi különös

Hátravan még az a kérdés, hogy hátha azért van ez, mert maga AIX-os ld belegyógyítja a teljes *.a archívot az executable-ba.
De nem. Ha veszem azt a parancsot, amit a collect2 dob a ld-nek, akkor ezt kapom:

$ make ./collect2_prob_ald
/usr/bin/ld -bpT:0x10000000 -bpD:0x20000000 -btextro -bnodelcsect \
-o collect2_prob_ald /lib/crt0.o -L/opt/freeware/lib/gcc/powerpc-ibm-aix6.1.0.0/4.6.4 -L/opt/freeware/lib/gcc/powerpc-ibm-aix6.1.0.0/4.6.4/../../.. collect2_main.o collect2_bait.a \
-lstdc++ -lm -lgcc_s \
/opt/freeware/lib/gcc/powerpc-ibm-aix6.1.0.0/4.6.4/libgcc.a \
-lc -lgcc_s \
/opt/freeware/lib/gcc/powerpc-ibm-aix6.1.0.0/4.6.4/libgcc.a

$ ./collect2_prob_ald
A főprogram vagyok, semmi különös

látszik, hogy nem ugrott rá a collect2_bait.a-ra, nem nem volt rá szüksége, nem volt unresolved externje.

Hozzászólások

Mondjuk a reprodukalashoz kellene a collect2_bait.a -ban levo class kodja...
--
Ki oda vágyik, hol száll a galamb, elszalasztja a kincset itt alant:


()=() 
('Y') Blog | @hron84
C . C Üzemeltető macik
()_()

/* collect2_bait.cc */

#include <cstdio>

class HibaProvokalo {
public:
    HibaProvokalo ();
};

HibaProvokalo::HibaProvokalo ()
{
    fprintf (stderr, "HibaProvokalo: Nekem qrvára nem kellene futnom\n");
    fflush (stderr);
}

HibaProvokalo hp;

Csak két feltétel van:

1. semmi köze se legyen a főprogramhoz
2. legyen benne egy globális változó, aminek a konstruktora le kell fusson még a main előtt

Linux, de a konkret valtozatot csak hetfon tudom megmondani, mert megbolondult a gepem, es nem ferek hozza a munkahelyi gephez itthonrol (nem indul a VPN vmiert). Ha minden igaz, akkor a main.o + bait.o verzio csinalja, a main.o + bait.a nem csinalja.

Az a lenyeg, hogy az --as-needed flagnak semmi hatasa nincs, pedig a main.o + bait.o verzioban is ki kellene csapkodnia azokat a szimbolumokat, amikre nem hivatkozik senki.
--
Ki oda vágyik, hol száll a galamb, elszalasztja a kincset itt alant:


()=() 
('Y') Blog | @hron84
C . C Üzemeltető macik
()_()

Ha effektív megadunk egy *.o -t a linkernek, azt általában beleteszi az eredménybe (persze ez is lehet platform/opciófüggő), az *.a nál viszont mazsolázni szokott a linker, hacsak nincs valami --whole-archive szerű opció (AIX-on például úgy szokunk shared libet csinálni, hogy előtte egy export listát csinálunk az összes input-elem exportált szimbólumából, és átadjuk a ld-nek (-bE:filenev), hogy 'na ezeket szeretnénk az outputban viszontlátni), így bele kell tennie mindent.)