[Bug ld/4538] New: static initialization ignored in static archive (.a)
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)
--- 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)
--- 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)
--- 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
--- 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