At Sun, 2 Mar 2025 23:34:32 +0000 (UTC), RVP <rvp%SDF.ORG@localhost> wrote: Subject: Re: static linking vs. __attribute__((constructor)) et al > > Yes (can effect dynamically-linked binaries too, for the same reason). I wouldn't expect any runtime linked libraries to suffer the same problem. They should have all the .o's in them, and any .ctors sections should have been combined into one. Then when ld.so_elf loads it "the right thing" should happen to ensure all the constructors from all the libraries (and any others from main .o files) should all be run by the C runtime startup. > I'm pretty sure that linker scripts won't help here, because by the time the > linker scripts are run to assemble the binary, the symbol resolution phase has > already happened and has discarded unreferenced objects. Hmmm.... yeah I was wondering about the order of execution. > You'll have to write a linker-plugin to do what you want. That defeats the purpose! (a static-linked linker can't load a plugin!) > (Writing any other > type of script to trawl through an `objdump -r' output, say, is likely to be > very fragile.) Fragile? Why? Seems easy enough to trawl through a library and find all the .o's with a .ctors section, then extract them and present them on the command line explicitly. That would guarantee all the relevant constructors are loaded and run at startup. No unreliability there. Of course wrapping /usr/bin/ld would be necessary to do that..... The only tricky thing is that some libraries are better designed than others such that they bundle the constructor functions with anything that might need them and so there's no need to separately look for .ctors sections -- e.g. libm(fenv.o) [and indeed libc as well]. The only harm of pulling in all objects with .ctors sections even if they're not needed by a program linking against a library like libm should be the extra space that object requires, plus the overhead of running the constructor when it's not needed. This already happens on one other platform: * On AIX, GCC scans object files and library archives for static constructors and destructors when linking an application before the linker prunes unreferenced symbols. This is necessary to prevent the AIX linker from mistakenly assuming that static constructor or destructor are unused and removing them before the scanning can occur. All static constructors and destructors found will be referenced even though the modules in which they occur may not be used by the program. This may lead to both increased executable size and unexpected symbol references. Of course this is all GCC's fault, plus that of those C++ programmers who don't know how to use C when they have to use C. > > Does anyone have any ideas of how to achieve successful static linking > > of libraries with constructors without -whole-archive and without > > using explicit references to all constructors? > > > > What's usually done is to use either `-u sym' or `--require-defined=sym' > on any of the syms (usually the constructor) in the object you want to pull in. That's what would be possible in a wrapper too I guess, though it can be a lot more complicated -- you have to find the names of all those symbols in all referenced libraries first though. They often show up in "objdump -x" output under the "RELOCATION RECORDS FOR [.ctors]:" sub-header for the .o containing the .ctors section, but sometimes they're off in a .text.startup section (e.g. libm(fenv.o)). The same caveat as above for libm would also still apply -- e.g. for libm getting fenv.o when it might not be needed otherwise. -- Greg A. Woods <gwoods%acm.org@localhost> Kelowna, BC +1 250 762-7675 RoboHack <woods%robohack.ca@localhost> Planix, Inc. <woods%planix.com@localhost> Avoncote Farms <woods%avoncote.ca@localhost>
Attachment:
pgpVVnV8y_UwH.pgp
Description: OpenPGP Digital Signature