QUESTION ON 2.95.2

Takis Psarogiannakopoulos takis@XFree86.org
Fri Dec 17 02:44:00 GMT 1999


Hello,

I have a question on gcc-2.95.2:
We try to compile mozilla M11 (C++) :
GCC version: 2.95.2
OS: DG/UX R4.20MU05

Inside a c++ source file (.cpp) we find the follwing code:

struct Components {
    const char* mDescription;
    const nsID* mCID;
    const char* mProgID;
};

// The list of components we register
static Components gComponents[] = {
    { "Script Security Manager", &nsScriptSecurityManager::GetCID(),
NS_SCRIPTSECURITYMANAGER_PROGID },
    { "Codebase Principal", &nsCodebasePrincipal::GetCID(),
NS_CODEBASEPRINCIPAL_PROGID }
};

#define NUM_COMPONENTS (sizeof(gComponents) / sizeof(gComponents[0]))
(so this is 2).

Note that the gComponents is declared static!

The only routines that use these gComponents structure are:
(both lying in the same .cpp where the above definitions).

NS_IMETHODIMP
nsSecurityManagerModule::RegisterSelf(nsIComponentManager *aCompMgr,
                             nsIFileSpec* aPath,
                             const char* registryLocation,
                             const char* componentType)

NS_IMETHODIMP
nsSecurityManagerModule::UnregisterSelf(nsIComponentManager* aCompMgr,
                               nsIFileSpec* aPath,
                               const char* registryLocation)


This .cpp file (together with others such .cpp files) will be compiled
with -fPIC and then do a ld -G (not GNU ld) to create a shared library say
libtest.so. (No other file in libtest.so has either the struct definition
of Components or the some other gComponents). 

When the main binary "mozilla-bin" calls the first library function 
nsSecurityManagerModule::RegisterSelf
the library libtest.so dumps core.
Close inspection of the core-file shows that gComponents is being
"cleared" by the c++-2.95.2. What I mean here is that if we move 
the defintion of (static!) gComponents INSIDE the two routines that
they use them, all are OK.
Example:

In the start of .cpp file we give

struct Components {
    const char* mDescription;
    const nsID* mCID;
    const char* mProgID;
};

and then later

NS_IMETHODIMP
nsSecurityManagerModule::RegisterSelf(nsIComponentManager *aCompMgr,
                             nsIFileSpec* aPath,
                             const char* registryLocation,
                             const char* componentType)

{
 
// The list of components we register
// no static needed anymore

Components g1Components[] = {
    { "Script Security Manager", &nsScriptSecurityManager::GetCID(),
NS_SCRIPTSECURITYMANAGER_PROGID },
    { "Codebase Principal", &nsCodebasePrincipal::GetCID(),
NS_CODEBASEPRINCIPAL_PROGID }
};

#define NUM_COMPONENTS_1 (sizeof(g1Components) / sizeof(g1Components[0]))


The rest of the function as was with replacement of 
NUM_COMPONENTS to NUM_COMPONENTS_1 and gComponents with g1Components.

....

}

all are back to normal.

Same thing for the second routine. Of course we eliminate from the
file the definition of gComponents as the routines that they use them 
they now include the definition inside the {}.

The question is why gcc-2.95.2 would not allocate the gComponents
when this is clearly declared as static.
All over mozilla M11 (other modules .so) we find the _exact_ same code
only that there works fine. Ie gcc-2.95.2 (c++) will allocate space for
the static gComponents. And bothe routines will be able to see them.
Any ideas why here fails to do so ??? 

(Linux gcc-2.95.2 will compile that part just fine also. Is there 
is some storage "limit" that causes some times gcc to fail on 
statics? ; at least for DG/UX).

Regards,
Takis

PS: 
Actually there is another issue that I would like to 
ask the list. DG/UX OS has no GNU ld (and is a no no!)
But defining USE_COLLECT2 will cause gcc-2.95.2 to not be able
to compile even the shared libstdc++.so.2.10.0 that comes with 
the 2.95.2 distribution. If we add use_collect2=yes in 
gcc/configure.in and create the shared lib libstdc++.so.2.10.0, 
when we try to compile a simple test c++ program we get:

bash# c++ test.cpp -o ii
Undefined                       first referenced
 symbol                             in file
global constructors keyed to streambuf::_un_link(void)/lib/libstdc++.so
global destructors keyed to streambuf::_un_link(void)/lib/libstdc++.so
UX:ld: ERROR: ii:
fatal error: Symbol referencing errors. No output written to ii
collect2: ld returned 1 exit status

collect2 -debug will give:

/usr/local/bin/gnm -n libstdc++.so.2.10.0

nm output with constructors/destructors.
        000335ec t _GLOBAL_.I._un_link__9streambuf
        00033618 t _GLOBAL_.D._un_link__9streambuf

1 constructor(s) found
1 destructor(s)  found
0 frame table(s) found
[Leaving libstdc++.so.2.10.0]

write_c_file - output name is libstdc++.so.2.10.0, prefix is libstdc___so

========== output_file = libstdc++.so.2.10.0, c_file = /var/tmp/ccSghnIh.c
#ifdef __cplusplus
extern "C" {
#endif
write_c_file - output name is libstdc++.so.2.10.0, prefix is libstdc___so
static int count;
typedef void entry_pt();
extern entry_pt x3 __asm__ ("_GLOBAL_.I._un_link__9streambuf");
void _GLOBAL__FI_libstdc___so() {
        static entry_pt *ctors[] = {
                x3,
        };
        entry_pt **p;
        if (count++ != 0) return;
        p = ctors + 1;
        while (p > ctors) (*--p)();
}
extern entry_pt x4 __asm__ ("_GLOBAL_.D._un_link__9streambuf");
void _GLOBAL__FD_libstdc___so() {
        static entry_pt *dtors[] = {
                x4,
        };
        entry_pt **p;
        if (--count != 0) return;
        p = dtors;
        while (p < dtors + 1) (*p++)();
}
void _GLOBAL__DI() {
        _GLOBAL__FI_libstdc___so();
}
void _GLOBAL__DD() {
        _GLOBAL__FD_libstdc___so();
}
#ifdef __cplusplus
}
#endif
========== end of c_file



Giving:

bash# nm libstdc++.so.2.10.0 | grep _GLOBAL_.D._un_link__9streambuf

[415]   |    211120|      40|FUNC |LOCL |0    |54
|_GLOBAL_.D._un_link__9streambuf
[737]   |         0|       0|NOTY |GLOB |0    |UNDEF
|_GLOBAL_.D._un_link__9streambuf

bash# nm libstdc++.so.2.10.0 | grep _GLOBAL_.I._un_link__9streambuf
[416]   |    211076|      40|FUNC |LOCL |0    |54
|_GLOBAL_.I._un_link__9streambuf
[560]   |         0|       0|NOTY |GLOB |0    |UNDEF
|_GLOBAL_.I._un_link__9streambuf

ie two (2) Undefined global symbols.


bash# /usr/bin/ld test.o -o ii -lstdc++ -lm -lc (link)

Undefined                       first referenced
 symbol                             in file
_GLOBAL_.I._un_link__9streambuf     /usr/local/lib/libstdc++.so
_GLOBAL_.D._un_link__9streambuf     /usr/local/lib/libstdc++.so

UX:ld: ERROR: ii: fatal error: Symbol referencing errors. No output
written to ii

So collect2 produces Undefined symbols when trying to find 
constuctors/destructors.


If we do not use use_collect2=yes in configure 
we get a shared libstdc++.so.2.10.0 that reports

bash# nm libstdc++.so | grep _un_link__9streambuf
[393]   |    204812|      40|FUNC |LOCL |0    |52
|_GLOBAL_.D._un_link__9streambuf
[394]   |    204768|      40|FUNC |LOCL |0    |52
|_GLOBAL_.I._un_link__9streambuf
[1361]  |    200116|      37|FUNC |GLOB |0    |52
|_un_link__9streambuf

and

bash# c++ test.cpp -o ii
will compile the test.cpp just fine.

Anybody knows why is that? And more importantly should we use 
use_collect2=yes when the DG/UX ld is not GNU. (-fgnu-linker
will be defined as default).



More information about the Gcc mailing list