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