dfhack
dfhack copied to clipboard
recent changes (to gcc?) are making some plugins ununloadable on linux
During the course of developing the port of suspendmanager to C++ @chdoc ran into difficulty reloading the development build of the plugin from a running DF using dfhack's reload command. Further investigation determined that this is because gcc is tagging various symbols in the built plugin with the STB_GNU_UNIQUE tag, which triggers libdl to mark the DLL as ununloadable.
The reason why gcc does this are complicated. but experimentation shows that adding --fno-gnu-unique to the gcc compile flags for that plugin prevents gcc from adding that tag.
Examination of the most recent CI build shows that the buildingplan, autoclothing and debug have symbols with the STB_GNU_UNIQUE tag set. It may be appropriate to set this compilation option for buildingplan and autoclothing but it is my expectation that setting it on debug will cause debug to fail.
The solution for debug may be to move the implementation of DFHack::DebugManager::getInstance() from DebugManager.h to DebugManager.cpp and to make the static instance variable a local variable in the implementation of that function, the way it is for Core::getInstance(). This should remove the reference to a static variable in an inline method that causes gcc to force the use of STB_GNU_UNIQUE (by making the method in question not inline).
In general, any function that needs to reference a class-level static variable must not be declared inline in the header file that defines that class; doing so will cause any plugin that uses that header file to be ununloadable. For translation units that include g++ standard classes that use inline references to class-level statics in their definitions, the --fno-gnu-unique flag can be added to the compilation options for that plugin, but only after verifying (using nm -C) that all of the symbols marked as such in the resulting plugins are either const data or functions whose implementation does not depend on static data local to the library unit, for which aliasing will be harmless. If the symbol points to non-const data or to a function whose implementation in the library unit is in any way different from that in dfhack's core, --fno-gnu-unique cannot be used.
This problem has the potential to become more severe in the future. When compiling DFHack on gcc-13.2 (specifically version 13.2.1_p20240113-r1 on Gentoo) there are a lot more plugins that have STB_GNU_UNIQUE symbols in them and are therefore tagged NODELTE:
$ for plug in *.plug.so; do if nm $plug | grep -q " u "; then echo "$plug (NODELETE)"; else echo $plug; fi; done
3dveins.plug.so (NODELETE)
RemoteFortressReader.plug.so (NODELETE)
add-spatter.plug.so (NODELETE)
autobutcher.plug.so (NODELETE)
autochop.plug.so (NODELETE)
autoclothing.plug.so (NODELETE)
autodump.plug.so (NODELETE)
autofarm.plug.so (NODELETE)
autolabor.plug.so (NODELETE)
autonestbox.plug.so
autoslab.plug.so (NODELETE)
blueprint.plug.so (NODELETE)
buildingplan.plug.so (NODELETE)
buildprobe.plug.so
burrow.plug.so (NODELETE)
changeitem.plug.so
changelayer.plug.so
changevein.plug.so
check-structures-sanity.plug.so (NODELETE)
cleanconst.plug.so
cleaners.plug.so
cleanowned.plug.so
color-dfhack-text.plug.so
counters.plug.so
createitem.plug.so
cursecheck.plug.so
cxxrandom.plug.so (NODELETE)
debug.plug.so (NODELETE)
deramp.plug.so
design.plug.so (NODELETE)
dig-now.plug.so (NODELETE)
dig.plug.so
dumpmats.plug.so
dwarfvet.plug.so
eventExample.plug.so
eventful.plug.so (NODELETE)
fastdwarf.plug.so
faststart.plug.so
filltraffic.plug.so
flows.plug.so
frozen.plug.so
getplants.plug.so
hotkeys.plug.so (NODELETE)
kittens.plug.so (NODELETE)
lair.plug.so
liquids.plug.so
logistics.plug.so (NODELETE)
luasocket.plug.so (NODELETE)
memview.plug.so
misery.plug.so
nestboxes.plug.so
onceExample.plug.so
orders.plug.so (NODELETE)
overlay.plug.so
pathable.plug.so
preserve-tombs.plug.so
probe.plug.so
prospector.plug.so (NODELETE)
ref-index.plug.so
regrass.plug.so
reveal.plug.so
seedwatch.plug.so (NODELETE)
showmood.plug.so
sort.plug.so
spectate.plug.so
stockcheck.plug.so
stockpiles.plug.so (NODELETE)
stocks.plug.so
strangemood.plug.so
stripcaged.plug.so
suspendmanager+.plug.so
tailor.plug.so (NODELETE)
tilesieve.plug.so
tiletypes.plug.so
tubefill.plug.so
tweak.plug.so (NODELETE)
vectors.plug.so
work-now.plug.so
xlsxreader.plug.so
zone.plug.so