[Bug ld/4538] New: static initialization ignored in static archive (.a)

2007-05-22 Thread ejt at andrew dot cmu dot edu
This is my $0.02 that I consider the ignoring of static initializers with side 
effects to be a bug, as per 
discussions at:
http://www.ecos.sourceware.org/ml/binutils/2003-04/msg00262.html
http://sources.redhat.com/ml/binutils/2003-02/msg00131.html

This recently cost me quite a bit of time to figure out why my code worked 
under OS X (shared libraries) 
but not linux (happened to be using static libraries), and it was eventually 
tracked down that since 
nothing explicitly referenced the translation unit, it was never linked in from 
the archive, and thus its 
static initialization was ignored.

Users writing auto-registration patterns will expect their code to register, 
and are going to be surprised 
when it fails to do so, particularly if it varies based on linking style.  
There is a nice list of workarounds 
here:
http://sources.redhat.com/ml/binutils/2003-02/msg00158.html
but each has shortcomings, mostly requiring end users of a library to have 
internal knowledge as to 
which symbols or files need to be explicitly imported, or requiring 
--whole-archive, which invalidates 
the point of using an archive.

The only argument in the threads referenced above *against* importing all 
static initialization sections 
was that it would load too many symbols from system libraries.  Hal Black 
points out this is not the 
case:
http://www.ecos.sourceware.org/ml/binutils/2003-04/msg00289.html
Although there are further hand-wavy counter-arguments regarding .ctor/.init 
sections, I'm not sure 
those would need to be imported to give the functionality we're looking for.

I would like to see some numbers there to prove that it is performance concern, 
since that appears to 
be the *only* reason to defend the current behavior, and is a demonstrated 
source of confusion and 
error.  If performance is indeed a valid case for leaving this issue open, 
there should at least be a better 
workaround provided...  for example:

OPTION A) Some kind of __attribute__ flag (i.e. 'used' or 'constructor') which 
marks that specific symbols 
be imported 'greedily' regardless of whether they are referenced.  This would 
keep knowledge about 
auto-registration in the code that's being registered, instead of requiring 
library end users to maintain 
a list of auto-registered classes in those libraries, which defeats the entire 
purpose of the pattern.

OPTION B) --all_init flag, similar to --whole_archive, but only the 
initalization sections (and their 
dependencies of course).  Some of us want our standards compliance in the 
spirit of the law, without 
having to resort to importing *everything*.

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. [hwb: see ** below]

-- 
   Summary: static initialization ignored in static archive (.a)
   Product: binutils
   Version: unspecified
Status: NEW
  Severity: normal
  Priority: P2
 Component: ld
AssignedTo: unassigned at sources dot redhat dot com
    ReportedBy: ejt at andrew dot cmu dot edu
CC: bug-binutils at gnu dot org


http://sourceware.org/bugzilla/show_bug.cgi?id=4538

--- You are receiving this mail because: ---
You are on the CC list for the bug, or are watching someone who is.


___
bug-binutils mailing list
bug-binutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-binutils


[Bug ld/4538] static initialization ignored in static archive (.a)

2007-05-22 Thread ejt at andrew dot cmu dot edu

--- Additional Comments From ejt at andrew dot cmu dot edu  2007-05-23 
05:23 ---
and your reason for this is statement is because...?

The C++ spec is pretty clear.  binutils is not handling linking of C++ code 
properly when it's in an archive.  
I get the idea of the archive is to only pull in what is needed.  Static 
initialization is expected, and thus 
needed, and not doing it is not handling the C++ spec.  Period.

So either this is a bug, or you should tell me binutils is only intended for C 
code... in which case I'll just 
re-submit this as a "feature request" for C++ support.

-- 
   What|Removed |Added

 Status|RESOLVED|REOPENED
 Resolution|INVALID |


http://sourceware.org/bugzilla/show_bug.cgi?id=4538

--- You are receiving this mail because: ---
You are on the CC list for the bug, or are watching someone who is.


___
bug-binutils mailing list
bug-binutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-binutils


[Bug ld/4538] static initialization ignored in static archive (.a)

2007-05-23 Thread ejt at andrew dot cmu dot edu

--- Additional Comments From ejt at andrew dot cmu dot edu  2007-05-23 
08:19 ---
Ah, but unfortunately Mr. Earnshaw was arguing up the wrong tree there.  Just 
because we understand 
why the current implementation is producing the results we see, doesn't mean 
the current 
implementation is *correct*.

As he says, the standard specifies how to handle sections in individual object 
files.  This defines the 
expected behavior.  However, the linker is not providing the expected behavior 
when the files happen 
to be in an archive, therefore it is breaking the spec in that case.  It 
doesn't matter that the spec doesn't 
say anything about archive formats, because it doesn't need to.  If I invent 
some new container format, 
and it breaks exception handling on any code stored within it, then it's 
breaking the spec by 
malforming handling of stuff that *is* covered by the spec.

If you want to claim to support C++ code, then you don't have carte blanche to 
give whatever random 
behavior you feel like -- the spec defines how code is supposed to be handled, 
and it's currently not 
happening.  

Correct me if I'm wrong, but the archive format is intended to speed up linking 
and simplify 
distribution, *not change the behavior of code which results*.  If the linker 
can strip/leave out unused 
code from an archive, that's a nice optimization, but if this causes a change 
in runtime results, then 
obviously that code wasn't unused after all, and was incorrect to leave it out!

I still don't see an explanation why you won't consider changing this incorrect 
behavior.  I read some 
performance concerns of questionable validity, and perhaps an issue with 
breaking existing code 
(apparently relying on *not* being run?!?).  Both of these can be resolved by 
using either of the options I 
suggested above.  Option A would probably be somewhat more difficult to 
implement, perhaps 
requiring a new section to be emitted by gcc, but I would expect Option B would 
be quite 
straightforward -- just a lighter version of --whole_archive, and it would 
allow those of us who want to 
use this language feature to do so without affecting anything else.

Finally, I'll point out this isn't just a C++ issue.  I've also tried using 
__attribute__((constructor)) on a 
function in C, and it has the same issues as these C++ initialization woes.  
You may consider the 
current status quo the pinnacle definition of 'what's expected', but I have a 
feeling library writers would 
like a way for constructor/initialization functions to be called reliably 
regardless of whether a symbol in 
the translation unit of that init code happens to be referenced.  That 
requirement is neither intuitive nor 
consistent nor spec conformant.

I'm not expecting this to be fixed overnight, but it's never going to be 
corrected if you stick by the "it's 
not a bug" line and refuse to leave this open for future consideration.


-- 
   What|Removed |Added

 Status|RESOLVED|REOPENED
 Resolution|INVALID |


http://sourceware.org/bugzilla/show_bug.cgi?id=4538

--- You are receiving this mail because: ---
You are on the CC list for the bug, or are watching someone who is.


___
bug-binutils mailing list
bug-binutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-binutils


[Bug ld/4538] static initialization ignored in static archive (.a)

2007-05-23 Thread ejt at andrew dot cmu dot edu

--- Additional Comments From ejt at andrew dot cmu dot edu  2007-05-23 
16:25 ---
> You are incorrect.  The standard does not cover archive libraries, and
> so the definition of "container" you're assuming has no basis in the
> standard.
It doesn't need to cover archives, containers, or any other such wrappers!
It covers what goes *into* the wrapper.  Your wrapper changes the behavior of 
the stuff that's inside, 
thus breaking what *is* covered and expected by the spec.

I consider this a bug, unless you want to argue that it's acceptable behavior 
for the archive to change 
the runtime results of code which is produced with it.  That's a very slippery 
slope, because then *any* 
bug report is going to be brushed off with this excuse.  Maybe you'd like that 
;)  But I prefer consistent 
executables whenever possible, and this is definitely possible.  You already 
have --whole_archive, just 
add --all_init (or something like that) so we don't have to throw the baby 
(faster links, reduced size) out 
with the bathwater (skipping initialization).

> I'm positive there are people relying on the current behavior.
> Changing it would be a bad idea.
** We don't have to change the current default behavior! **
My suggested solutions wouldn't affect current code:
Just add a flag so that people who are relying on this aren't bothered, and 
those of us who expect 
proper functionality can get it without sacrificing the archive format 
altogether.


-- 


http://sourceware.org/bugzilla/show_bug.cgi?id=4538

--- You are receiving this mail because: ---
You are on the CC list for the bug, or are watching someone who is.


___
bug-binutils mailing list
bug-binutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-binutils


[Bug ld/4538] add --all-init flag to force all static initializers to be loaded

2007-08-06 Thread ejt at andrew dot cmu dot edu

--- Additional Comments From ejt at andrew dot cmu dot edu  2007-08-07 
03:37 ---
Such a good, persuasive argument!  You've raised many good points that I hadn't 
considered...
OK then, lets call it an "enhancement", and I'll reword the summary for you.

The fact that this issue keeps coming up (see referenced threads at the 
beginning of the thread) should 
tell you that this is an ongoing problem for users.  I don't see why you refuse 
to even consider the 
option of fixing it.  For heaven's sake, no one says *you* have to do it, just 
leave the report open as a 
known issue so people can track it and maybe someday someone *else* will be 
inspired to give it a 
shot.

And for reference, here's the work around I've personally settled on in the 
mean time: I added a pre-
linking step to my Makefile to scan for symbols named 'autoRegister*', and then 
pass '-u' flags for each 
of those symbols when doing the final link to make sure their initializers get 
pulled in, like so:
@undef=`nm -g "project.a" | grep "autoRegister" | grep -v " *U" | cut 
-f 3 -d ' ' | sort -u | sed 
's/^/-u /'`; \
$(CXX) -o $@ $$undef $(OBJS) $(libs)  ;

Of course, it'd sure be nice to have an "official" way to handle this that 
doesn't involve specially-named 
symbols or bash scripts wrapped around the linker... e.g. adding a --all-init 
flag, perhaps?

-- 
   What|Removed |Added

   Severity|normal  |enhancement
 Status|RESOLVED|REOPENED
 Resolution|INVALID |
Summary|static initialization   |add --all-init flag to force
   |ignored in static archive   |all static initializers to
   |(.a)|be loaded


http://sourceware.org/bugzilla/show_bug.cgi?id=4538

--- You are receiving this mail because: ---
You are on the CC list for the bug, or are watching someone who is.


___
bug-binutils mailing list
bug-binutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-binutils