public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
@ 2003-04-11  3:43 Hal Black
  2003-04-11  4:47 ` Alexandre Oliva
  2003-04-11  8:16 ` Alan Modra
  0 siblings, 2 replies; 17+ messages in thread
From: Hal Black @ 2003-04-11  3:43 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 1442 bytes --]

Using GNU ld version 2.13.90.0.18 20030206 (comes with Redhat 9)
Also experienced with previous 3.x and 2.9x versions.

When linking with a bunch of .o files, the desired behavior (static 
initializers are called) happens.  But when linking .a files composed of 
those .o files, static initializers are not called.  On the other hand, 
when the .cpp files are combined to make a single .o file, which is then 
  used to form a .a file, that works.

This was previously reported to gcc bugs, but they sent me here (I've 
been lurking for quite a while to see if it was okay to post bugs here):
http://gcc.gnu.org/cgi-bin/gnatsweb.pl (bug 7769)

There is some good discussion there.

Full source code and makefile follows in the attachment.  See below for 
a quick glance of what I'm talking about.

one.cc
------
#include <stdio.h>

class A {
public:
	A() { printf("Hello world!\n"); }
};
A a;
------

two.cc
------
int main() {}
------

combined.cc
-----------
#include "one.cc"
#include "two.cc"
-----------

Makefile
--------
CPP=g++
test:main1 main2 main3 main4
	./main1
	./main2
	./main3
	./main4
%.o:%.cc
	$(CPP) -c $<
lib%.a:%.o
	ar rv $@ $<
both.a:one.o two.o
	ar rv $@ $^
main1:one.o two.o
	$(CPP) one.o two.o -o main1
main2:libone.a libtwo.a
	$(CPP) libone.a libtwo.a -o main2
main3:both.a
	$(CPP) both.a -o main3
main4:libcombined.a
	$(CPP) libcombined.a -o main4
clean:
	rm -f *.a *.o main*
--------


thanks for your time.
   Hal

[-- Attachment #2: static_init.tar.bz2 --]
[-- Type: application/octet-stream, Size: 554 bytes --]

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-11  3:43 [BUG] ld behavior varies for C++ static initializer depending on .a or .o input Hal Black
@ 2003-04-11  4:47 ` Alexandre Oliva
  2003-04-12  4:01   ` Hal Black
  2003-04-11  8:16 ` Alan Modra
  1 sibling, 1 reply; 17+ messages in thread
From: Alexandre Oliva @ 2003-04-11  4:47 UTC (permalink / raw)
  To: Hal Black; +Cc: binutils

On Apr 11, 2003, Hal Black <hablack@vt.edu> wrote:

> But when linking .a files composed
> of those .o files, static initializers are not called.

And, if you look closer, you'll notice the object files that contain
the initializers aren't linked in at all.  Which is perfectly fine,
given that no symbols from it are referenced.  Maybe you want
--whole-archive?

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-11  3:43 [BUG] ld behavior varies for C++ static initializer depending on .a or .o input Hal Black
  2003-04-11  4:47 ` Alexandre Oliva
@ 2003-04-11  8:16 ` Alan Modra
  1 sibling, 0 replies; 17+ messages in thread
From: Alan Modra @ 2003-04-11  8:16 UTC (permalink / raw)
  To: Hal Black; +Cc: binutils

On Thu, Apr 10, 2003 at 11:43:53PM -0400, Hal Black wrote:
> When linking with a bunch of .o files, the desired behavior (static 
> initializers are called) happens.  But when linking .a files composed of 
> those .o files, static initializers are not called.

See http://sources.redhat.com/ml/binutils/2003-02/msg00155.html

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-11  4:47 ` Alexandre Oliva
@ 2003-04-12  4:01   ` Hal Black
  2003-04-12  5:43     ` Alexandre Oliva
  0 siblings, 1 reply; 17+ messages in thread
From: Hal Black @ 2003-04-12  4:01 UTC (permalink / raw)
  To: binutils

Alexandre Oliva wrote:
> On Apr 11, 2003, Hal Black <hablack@vt.edu> wrote:
> 
> 
>>But when linking .a files composed
>>of those .o files, static initializers are not called.
> 
> 
> And, if you look closer, you'll notice the object files that contain
> the initializers aren't linked in at all.  Which is perfectly fine,
> given that no symbols from it are referenced.  Maybe you want
> --whole-archive?
> 

Thanks Alexandre, for replying and the --whole-archive tip - it works 
great (has to be -Wl,-whole-archive when passed to g++, though, as noted 
on the man page).

I still believe this is a bug, however.  Even though there aren't any 
references to static intializers, there is an implicit reference to 
them.  When using .o files, there are no references either, but the 
static intializer is included in that case.  Why should it be different 
for a .a file with the same .o files in it?  Should .a files not be used 
for C++?

Perhaps the solution is to pass --whole-archive by default to ld when 
linking with g++.

But, at least there is a workaround.

Thanks also to Alan for the reference, I don't know how I missed that 
thread.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-12  4:01   ` Hal Black
@ 2003-04-12  5:43     ` Alexandre Oliva
  2003-04-12 14:24       ` Hal Black
  0 siblings, 1 reply; 17+ messages in thread
From: Alexandre Oliva @ 2003-04-12  5:43 UTC (permalink / raw)
  To: Hal Black; +Cc: binutils

On Apr 12, 2003, Hal Black <hablack@vt.edu> wrote:

> Why should it be different for a .a file with the same .o files in
> it?  Should .a files not be used for C++?

Because .o files are copied to the output, whereas .a files are used
as libraries, i.e., only members that offer symbols that are being
looked for are copied to the output.  Can you imagine the bloat if any
time you linked with a static library, all of the code in it was
copied to your executables?

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-12  5:43     ` Alexandre Oliva
@ 2003-04-12 14:24       ` Hal Black
  2003-04-12 16:52         ` Ian Lance Taylor
  0 siblings, 1 reply; 17+ messages in thread
From: Hal Black @ 2003-04-12 14:24 UTC (permalink / raw)
  To: binutils

Alexandre Oliva wrote:
> On Apr 12, 2003, Hal Black <hablack@vt.edu> wrote:
> 
> 
>>Why should it be different for a .a file with the same .o files in
>>it?  Should .a files not be used for C++?
> 
> 
> Because .o files are copied to the output, whereas .a files are used
> as libraries, i.e., only members that offer symbols that are being
> looked for are copied to the output.  Can you imagine the bloat if any
> time you linked with a static library, all of the code in it was
> copied to your executables?

What I'm saying is not to use all the symbols, but to include all static 
initializers as "symbols that are being looked for".  Even if they 
aren't explicitly referenced by annother piece of code, they are 
implicitly referenced by virtue of being static initializers.


------------------
   From the C++ draft spec 2 December 1996:

  Section 3.7.1:
  2 If an object of static storage duration has initialization or a
  destructor with side effects, it shall not be eliminated even if it
  appears to be unused, except that a class object or its copy may be
  eliminated as specified in 12.8.
------------------

I would say that not looking for static initializers constitutes 
eliminating them...

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-12 14:24       ` Hal Black
@ 2003-04-12 16:52         ` Ian Lance Taylor
  2003-04-12 18:01           ` Hal Black
  0 siblings, 1 reply; 17+ messages in thread
From: Ian Lance Taylor @ 2003-04-12 16:52 UTC (permalink / raw)
  To: Hal Black; +Cc: binutils

Hal Black <black@ieee.org> writes:

> What I'm saying is not to use all the symbols, but to include all
> static initializers as "symbols that are being looked for".  Even if
> they aren't explicitly referenced by annother piece of code, they are
> implicitly referenced by virtue of being static initializers.

That would mean that every static initializer in a .a file would be
brought in, which would doubtless bring in other object files as well.
It means that including any class with a static initializer in a .a
file would mean that that class would be included in all programs
linked with that .a file.  This would go against the very idea of a .a
file, which is that only required objects are included.

> I would say that not looking for static initializers constitutes
> eliminating them...

No, because they were never included in the first place.

It's reasonably easy to avoid this problem: put the static initializer
in the same source file as a class virtual function.  Since the
class virtual function must be included, the initializer will be
brought in as well.

If you don't have any virtual functions, then you do need to take some
other action to force that object file to be included, such as using
global variables in some way.

Or maybe .a files are simply the wrong tool for the job.  Maybe you
should use ld -r to form several .o files into one large .o file.
Linking against that will ensure that everything is brought in.

Ian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-12 16:52         ` Ian Lance Taylor
@ 2003-04-12 18:01           ` Hal Black
  2003-04-12 20:45             ` Alexandre Oliva
  2003-04-13 22:55             ` Ian Lance Taylor
  0 siblings, 2 replies; 17+ messages in thread
From: Hal Black @ 2003-04-12 18:01 UTC (permalink / raw)
  To: binutils

Thanks for replying, Ian.

Ian Lance Taylor wrote:

> Hal Black <black@ieee.org> writes:
> 
> 
>>What I'm saying is not to use all the symbols, but to include all
>>static initializers as "symbols that are being looked for".  Even if
>>they aren't explicitly referenced by annother piece of code, they are
>>implicitly referenced by virtue of being static initializers.
> 
> 
> That would mean that every static initializer in a .a file would be
> brought in

Yes, as desired.

 > which would doubtless bring in other object files as well.

If the static initializer calls other functions, then those would be 
required as well, just as normal ld behavior.

> It means that including any class with a static initializer in a .a
> file would mean that that class would be included in all programs
> linked with that .a file.

Yes.  That's the desired behavior.  If a developer were to develop a 
library with a static initializer with side-effects, it would be 
something that should be called whenever that library was used.

Other classes with no static initializers would only be used as needed, 
as they are now.

If you don't think this is the proper usage, what is your interpretation 
of the meaning of having a static intializer (or items with static 
storage duration in general) in a library?

 >  This would go against the very idea of a .a
> file, which is that only required objects are included.

My claim is that if it has a static initializer, it is required.  If it 
is called from any included object, it is required (as it works now). 
Therefore this doesn't break the idea the only required objects are 
included.

-----
Also, just to clarify since it got lost in the quoting, I'm talking 
about this scenario:

class A {
public:
     A() { printf("Hello world!\n"); }
};
A a;

I claim if this code is put in a library, printf should be called. 
Because "a" has static storage duration and has side effects, its 
initializer cannot be eliminated per 3.7.1.2 of the draft standard.

So, when I say static initializer in the context of this discussion, the 
above code fragment is what I mean.

>>I would say that not looking for static initializers constitutes
>>eliminating them...
> 
> No, because they were never included in the first place.

The claim is that never including them in the first place is elimination.

> It's reasonably easy to avoid this problem: put the static initializer
> in the same source file as a class virtual function.  Since the
> class virtual function must be included, the initializer will be
> brought in as well.

The claim is that static initializers as specified above are in this 
same category of things that must be included.

> If you don't have any virtual functions, then you do need to take some
> other action to force that object file to be included, such as using
> global variables in some way.
> 
> Or maybe .a files are simply the wrong tool for the job.  Maybe you
> should use ld -r to form several .o files into one large .o file.
> Linking against that will ensure that everything is brought in.

Thanks for large .o idea.  This, and other workarounds such as the one 
provided by Alexandre, would work great for my immediate purposes.

However, I'm not having a problem finding a workaround, I'm addressing 
the point of how static initializers should behave in a library.  The 
workarounds proposed, though they work great as a fix for what I was 
having problems with, don't provide library functionality (only include 
what's needed).  Also, they require extra steps to use common 
implementations of automatic registration patterns in a library.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-12 18:01           ` Hal Black
@ 2003-04-12 20:45             ` Alexandre Oliva
  2003-04-13  2:11               ` Hal Black
  2003-04-13 22:55             ` Ian Lance Taylor
  1 sibling, 1 reply; 17+ messages in thread
From: Alexandre Oliva @ 2003-04-12 20:45 UTC (permalink / raw)
  To: Hal Black; +Cc: binutils

On Apr 12, 2003, Hal Black <black@ieee.org> wrote:

>> That would mean that every static initializer in a .a file would be
>> brought in

> Yes, as desired.

Maybe in your specific application.  But think of the Standard C++
library.  It may contain hundreds, if not thousands, of global
initializers, that are of no use for most programs that don't happen
to use the particular feature that depend on some of these
initializers.  Bringing them in just because you would like it to be
so is not exactly a reasonable proposition.

> If you don't think this is the proper usage, what is your
> interpretation of the meaning of having a static intializer (or items
> with static storage duration in general) in a library?

No different from having it in an object file: if the object file is
linked in, the static initializer is run.  The difference is that
object files listed in the command line are always linked in, whereas
those in a static library get linked in only if they would resolve
some symbol the linker is looking for.

> My claim is that if it has a static initializer, it is required.

If we implemented this mis-feature, you'll come back tomorrow and
complain about the bloat from all these modules being linked in that
are not needed for your program to run, and the answer will be that
they do contain static initializers so, per your request, they have to
be brought in.

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-12 20:45             ` Alexandre Oliva
@ 2003-04-13  2:11               ` Hal Black
  2003-04-14 18:41                 ` Alexandre Oliva
  0 siblings, 1 reply; 17+ messages in thread
From: Hal Black @ 2003-04-13  2:11 UTC (permalink / raw)
  To: binutils

Alexandre Oliva wrote:

> On Apr 12, 2003, Hal Black <black@ieee.org> wrote:
> 
> 
>>>That would mean that every static initializer in a .a file would be
>>>brought in
> 
> 
>>Yes, as desired.
> 
> 
> Maybe in your specific application.  But think of the Standard C++
> library.  It may contain hundreds, if not thousands, of global
> initializers, that are of no use for most programs that don't happen
> to use the particular feature that depend on some of these
> initializers.

I'm not an expert on g++ symbols, but I'm assuming the static intializer 
of the sort I'm talking about is is named 
__static_initialization_and_detruction.* because that's what nm reports 
for my test program.

When I run nm on libstdc++*.a and grep for static_initialization, I get 
not thousands, not hundreds, but zero matches.  So, if I'm right about 
the naming, the program would get no bigger if the changes I suggested 
were implemented.

OTOH, I could be totally wrong.  8')  I really know nothing about the 
details of how g++ does naming of C++ constructs.

[caveat: I don't have access to the latest stuff right now, this is with 
mandrake 9.0 - maybe they have added thousands of static initializers 
since then]

I counted 18 static initializers total in /usr/lib.  I don't know 
whether these are meant to be called every time the library is linked 
against, or just when a certain feature is used.

 > Bringing them in just because you would like it to be
> so is not exactly a reasonable proposition.

It's not a question of me liking it to be so.  I have already stated 
that I am fine with the work around.  I am raising the point how the C++ 
spec is interpreted in terms of libraries for discussion.  The way to 
dispute this point is to argue against the point, not wave it off 
because you infer endearment of an individual to it, which is irrelevant 
on whether it is the right way to do it or not.

I just hadn't heard any valid reasons against having it be as I 
describe, and it seems like the correct interpretation of the spec.

>>If you don't think this is the proper usage, what is your
>>interpretation of the meaning of having a static intializer (or items
>>with static storage duration in general) in a library?
> 
> 
> No different from having it in an object file: if the object file is
> linked in, the static initializer is run.  The difference is that
> object files listed in the command line are always linked in, whereas
> those in a static library get linked in only if they would resolve
> some symbol the linker is looking for.

I understand the behavior of the tools.  What I asked was what is the 
meaning of having objects with static storage in a library.

Based on an earlier portion of your reply, I am taking your 
interpretation to mean that a static initializer in a library is only 
called when something references an instance of its class or members, 
but not otherwise.  I don't believe this is a valid view from reading 
the C++ spec.

>>My claim is that if it has a static initializer, it is required.
> 
> 
> If we implemented this mis-feature, you'll come back tomorrow and
> complain about the bloat from all these modules being linked in that
> are not needed for your program to run, and the answer will be that
> they do contain static initializers so, per your request, they have to
> be brought in.

If they were not needed for the program to run, the behavior (not 
counting performance/memory footprint for the moment) would be the same 
whether they were included or not.  Desired side-effects of the static 
initializers don't happen when they're not included, therefore they are 
required for the program to run.

I see your point that if the custom is to put in instances of static 
storage whose initializers aren't meant to be called all the time, some 
uneccesary bloat could result.  If they are supposed to be called, 
however, they aren't unneccesary.

I don't know whether the 18 static initializers in my /usr/lib are meant 
to be used the way I describe or the way you describe, so I can't say 
whether these are unneccesary or neccesary.

Regardless, if my interpretation of the C++ spec is correct, it is a 
flaw in the library to create static storage items with initializers 
with side effects that aren't meant to be run for all users of the 
library.  In that case, the linker would be following the spec and would 
deserve no complaints.  It's not the auto-maker's fault if the car is 
working fine and you get caught speeding.

But, if you don't want to implement it to avoid complaints, it's your 
project, not mine, so I can't argue with that.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-12 18:01           ` Hal Black
  2003-04-12 20:45             ` Alexandre Oliva
@ 2003-04-13 22:55             ` Ian Lance Taylor
  2003-04-13 23:07               ` Zack Weinberg
  2003-04-14  5:14               ` Hal Black
  1 sibling, 2 replies; 17+ messages in thread
From: Ian Lance Taylor @ 2003-04-13 22:55 UTC (permalink / raw)
  To: Hal Black; +Cc: binutils

Hal Black <black@ieee.org> writes:

> > It means that including any class with a static initializer in a .a
> > file would mean that that class would be included in all programs
> > linked with that .a file.
> 
> Yes.  That's the desired behavior.  If a developer were to develop a
> library with a static initializer with side-effects, it would be
> something that should be called whenever that library was used.

No Unix linker has ever worked that way.

Basically, you misunderstand how ld and ar work.  If you feel that you
have been misled by existing documentation, please let us know so that
we can fix it.

Also, while this is not the reason for not making the change, it turns
out that it is not an efficient change to make.  It would require the
linker to examine every object in every archive, which obviates the
entire point of having archives in the first place.  Again, this
inefficiency, while severe, is not the reason for not making the
change; the reason for not making the change is that ld and ar
implement behaviour which has not changed for decades, and should not
be changed now.

Ian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-13 22:55             ` Ian Lance Taylor
@ 2003-04-13 23:07               ` Zack Weinberg
  2003-04-13 23:15                 ` Ian Lance Taylor
  2003-04-13 23:26                 ` Ulrich Drepper
  2003-04-14  5:14               ` Hal Black
  1 sibling, 2 replies; 17+ messages in thread
From: Zack Weinberg @ 2003-04-13 23:07 UTC (permalink / raw)
  To: binutils; +Cc: black

Ian Lance Taylor <ian@airs.com> writes:

> Hal Black <black@ieee.org> writes:
>> Yes.  That's the desired behavior.  If a developer were to develop a
>> library with a static initializer with side-effects, it would be
>> something that should be called whenever that library was used.
>
> No Unix linker has ever worked that way.
>
> Basically, you misunderstand how ld and ar work.  If you feel that you
> have been misled by existing documentation, please let us know so that
> we can fix it.

I'd like to point out that while this is true for static (.a)
libraries, it is not true for shared (.so) libraries -- the linker
generates DT_NEEDED entries for every shared library on the command
line, whether or not they satisfy undefined symbols.  Personally I
consider this a bug.

zw

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-13 23:07               ` Zack Weinberg
@ 2003-04-13 23:15                 ` Ian Lance Taylor
  2003-04-13 23:26                 ` Ulrich Drepper
  1 sibling, 0 replies; 17+ messages in thread
From: Ian Lance Taylor @ 2003-04-13 23:15 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: binutils, black

Zack Weinberg <zack@codesourcery.com> writes:

> Ian Lance Taylor <ian@airs.com> writes:
> 
> > Hal Black <black@ieee.org> writes:
> >> Yes.  That's the desired behavior.  If a developer were to develop a
> >> library with a static initializer with side-effects, it would be
> >> something that should be called whenever that library was used.
> >
> > No Unix linker has ever worked that way.
> >
> > Basically, you misunderstand how ld and ar work.  If you feel that you
> > have been misled by existing documentation, please let us know so that
> > we can fix it.
> 
> I'd like to point out that while this is true for static (.a)
> libraries, it is not true for shared (.so) libraries -- the linker
> generates DT_NEEDED entries for every shared library on the command
> line, whether or not they satisfy undefined symbols.  Personally I
> consider this a bug.

I think that one is debatable.  It's certainly true that shared
libraries and archive libraries don't work the same way; as you say,
one obvious difference is in fact the very one we are talking
about--all static initializers in a shared library are run, whether
they are required or not.  There are a number of other
differences--only in simple case can you just replace a .a file with a
.so file.

I think the general attitude of linker implementors has been that if
you list a shared library on the command line, you must want it in
there.  That is, a .so file is in that sense more like a .o file than
a .a file.

But I agree that it could be argued the other way.  I don't know of
any ELF linker which does not generate a DT_NEEDED for a .so listed on
the command line, but perhaps there is one.

Ian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-13 23:07               ` Zack Weinberg
  2003-04-13 23:15                 ` Ian Lance Taylor
@ 2003-04-13 23:26                 ` Ulrich Drepper
  1 sibling, 0 replies; 17+ messages in thread
From: Ulrich Drepper @ 2003-04-13 23:26 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: binutils, black

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Zack Weinberg wrote:

> I'd like to point out that while this is true for static (.a)
> libraries, it is not true for shared (.so) libraries -- the linker
> generates DT_NEEDED entries for every shared library on the command
> line, whether or not they satisfy undefined symbols.  Personally I
> consider this a bug.

Agreed, I argued like that for years.  If somebody wants the DSO
included s/he can use -u to create and artificial dependency.

- -- 
- --------------.                        ,-.            444 Castro Street
Ulrich Drepper \    ,-----------------'   \ Mountain View, CA 94041 USA
Red Hat         `--' drepper at redhat.com `---------------------------
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.1 (GNU/Linux)

iD8DBQE+mfH72ijCOnn/RHQRAtHmAKCnq3OcfkKWRnvmmZI9cyTLCzkeGgCfej6g
ZErCJSskzy+8TJD3Ld+CWos=
=9jUv
-----END PGP SIGNATURE-----

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-13 22:55             ` Ian Lance Taylor
  2003-04-13 23:07               ` Zack Weinberg
@ 2003-04-14  5:14               ` Hal Black
  2003-04-14  5:30                 ` Ian Lance Taylor
  1 sibling, 1 reply; 17+ messages in thread
From: Hal Black @ 2003-04-14  5:14 UTC (permalink / raw)
  To: binutils

Ian Lance Taylor wrote:

> Hal Black <black@ieee.org> writes:
> 
> 
>>>It means that including any class with a static initializer in a .a
>>>file would mean that that class would be included in all programs
>>>linked with that .a file.
>>
>>Yes.  That's the desired behavior.  If a developer were to develop a
>>library with a static initializer with side-effects, it would be
>>something that should be called whenever that library was used.
> 
> 
> No Unix linker has ever worked that way.

Well, for most of the lifetime of Unix, there were no static 
initializers, since there was no C++, so this is not surprising.

> Also, while this is not the reason for not making the change, it turns
> out that it is not an efficient change to make.  It would require the
> linker to examine every object in every archive, which obviates the
> entire point of having archives in the first place.  Again, this
> inefficiency, while severe, is not the reason for not making the
> change; the reason for not making the change is that ld and ar
> implement behaviour which has not changed for decades, and should not
> be changed now.

For the C code that ld has been linking for decades, I agree with you 100%.

But, C++ has additional requirements.  Either the tool needs to change 
to meet these requirements, or a different tool needs to be used to meet 
them.

If .a is meant only for what it has been used for decades without 
changing to accomodate the full C++ specification, you're right, I 
misunderstood the usage for it.  That is definately not what I want. 
Based on the other replies, I guess that .so can be used to acheive the 
desired behavior even though it includes too much.

Anyway, thank you for responding and for your time, Ian.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-14  5:14               ` Hal Black
@ 2003-04-14  5:30                 ` Ian Lance Taylor
  0 siblings, 0 replies; 17+ messages in thread
From: Ian Lance Taylor @ 2003-04-14  5:30 UTC (permalink / raw)
  To: Hal Black; +Cc: binutils

Hal Black <black@ieee.org> writes:

> > No Unix linker has ever worked that way.
> 
> Well, for most of the lifetime of Unix, there were no static
> initializers, since there was no C++, so this is not surprising.

C++ has had static initializers at least since 1985, so it's not all
that new.

> If .a is meant only for what it has been used for decades without
> changing to accomodate the full C++ specification, you're right, I
> misunderstood the usage for it.  That is definately not what I
> want. Based on the other replies, I guess that .so can be used to
> acheive the desired behavior even though it includes too much.

I'm not sure in what sense a .so file includes too much.  A .so file
is a very rough replacement for a .a file, so the fact that it
includes everything which is in the .a file is a feature.  It's true
that a .so file will always run all the static initializers which are
found in the .a file, but that's the very feature you want to
implement.  There are various differences in the implementation of
common symbols, but C++ disallows common symbols so that shouldn't
matter too much.  Warning symbols no longer work correctly, but that
is a GNU extension anyhow.  A .so is admittedly slightly slower, but
that rarely matters these days.

So what are your concerns with using a .so?

Ian

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [BUG] ld behavior varies for C++ static initializer depending on .a or .o input
  2003-04-13  2:11               ` Hal Black
@ 2003-04-14 18:41                 ` Alexandre Oliva
  0 siblings, 0 replies; 17+ messages in thread
From: Alexandre Oliva @ 2003-04-14 18:41 UTC (permalink / raw)
  To: Hal Black; +Cc: binutils

On Apr 12, 2003, Hal Black <black@ieee.org> wrote:

> I'm not an expert on g++ symbols, but I'm assuming the static
> intializer of the sort I'm talking about is is named
> __static_initialization_and_detruction.* because that's what nm
> reports for my test program.

Watch out for .ctor, .init or .init_array sections as well.

> I just hadn't heard any valid reasons against having it be as I
> describe, and it seems like the correct interpretation of the spec.

I disagree.  The compiler, which is the entity that deals with
translation units, isn't dropping any initializers, just like mandated
by the spec.  Now, by the Standard, a program is one or more
translation units linked together [basic.link], and that's it.
Nowhere does it get into details of what a linker is, nevermind how
static archives should behave, since this is all far beyond the scope
of the C++ Standard.

Your point that archives should be scanned for initializers would be
perfectly reasonable, except for the bloat one wouldn't be able to
avoid, but, like Ian says, this is not the way linkers have dealt with
archives in the past and, barring a strong reason to change, they
should change.  Standard compliance is not such a reason, because the
nowhere does the standard determine how to select the translation
units that go into a program.  

> Based on an earlier portion of your reply, I am taking your
> interpretation to mean that a static initializer in a library is only
> called when something references an instance of its class or members,
> but not otherwise.  I don't believe this is a valid view from reading
> the C++ spec.

My interpretation is that a static initializer in a translation unit
is only executed if the translation unit makes it to the program.  The
point under debate is whether the translation unit must make it to the
program in spite of not being referenced by any other translation unit
listed in the program.  If you have such requirements, using an
archive is the wrong approach: you want to list the object files
instead.

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                 aoliva@{redhat.com, gcc.gnu.org}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist                Professional serial bug killer

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2003-04-14 18:41 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-11  3:43 [BUG] ld behavior varies for C++ static initializer depending on .a or .o input Hal Black
2003-04-11  4:47 ` Alexandre Oliva
2003-04-12  4:01   ` Hal Black
2003-04-12  5:43     ` Alexandre Oliva
2003-04-12 14:24       ` Hal Black
2003-04-12 16:52         ` Ian Lance Taylor
2003-04-12 18:01           ` Hal Black
2003-04-12 20:45             ` Alexandre Oliva
2003-04-13  2:11               ` Hal Black
2003-04-14 18:41                 ` Alexandre Oliva
2003-04-13 22:55             ` Ian Lance Taylor
2003-04-13 23:07               ` Zack Weinberg
2003-04-13 23:15                 ` Ian Lance Taylor
2003-04-13 23:26                 ` Ulrich Drepper
2003-04-14  5:14               ` Hal Black
2003-04-14  5:30                 ` Ian Lance Taylor
2003-04-11  8:16 ` Alan Modra

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).