So, as you all probably know I build static-linked NetBSD systems. I'm now in the process of doing this for -current (amd64). I've got far enough to build an install (and live) image and install it and boot it and run it in a VM. Previously my most recent successful builds, which I've used in production since, have been with an old -current from, I think, 2021/03/10. sys/param.h says 9.99.81 Since then some key libraries, notably libisc, have gained the use of __attribute__((contructor)) functions. So, for example. /usr/bin/host won't work static-linked as-is. # host more.local /Volumes/work/woods/g-NetBSD-src/external/mpl/bind/lib/libisc/../../dist/lib/isc/mem.c:475:mem_create(): fatal error: pthread_mutex_init(): Invalid argument (22) Abort (core dumped) The problem facing successful static-linking is that the objects containing those constructor functions (i.e. from libraries) often/usually won't get linked into the final binary, and so of course they can never be run, usually leaving key data structures uninitialised. One trick often used in this situation is to simply ask the linker to pull in the whole archive (i.e. using -Wl,-whole-archive, as if it were one massive .o -- and indeed that's another related trick, i.e. convert such libraries to single .o's). This works, and it does produce working binaries. I tested with host: # ./host more.local more.local has address 10.0.1.129 That can be pretty wasteful though, e.g. host blows up by about 140kb: $ size host host- /usr/bin/host text data bss dec hex filename 6664304 486320 2211289 9361913 8ed9f9 /usr/bin/host 6803032 487776 2211353 9502161 90fdd1 ./host Another trick is to explicitly reference the constructor (and destructor) function(s) from some other primary object that's always loaded, but then one needs to know all their symbol names, and to modify all the programs that use any such libraries. I think the right solution is to ask the linker to pull in any and all objects from any and all mentioned libraries if they have a .ctors section. I don't see any obvious way to do this, but my understanding of GNU ld linker scripts is very limited. 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? Luckily in NetBSD it appears only a relatively few libraries have .o's with .ctors where those won't get pulled in by normal static linking (e.g. libc.a(initfini.o) gets pulled in because crt0.c refers explicitly to _libc_init). I still have to do a bit more careful audit though. -- 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:
pgpZCwbbsnGtD.pgp
Description: OpenPGP Digital Signature