From 837a54d9cef067a6fd6fa60b5f7183da6be22e77 Mon Sep 17 00:00:00 2001 From: riastradh Date: Wed, 20 Mar 2024 13:50:37 +0000 Subject: [PATCH] bsd.lib.mk: Check expected vs actual symbols at build-time. If, for LIB=foo, you create a file foo.expsym, bsd.lib.mk will list the dynamic symbols and their versions with nm --dynamic --extern-only --defined-only --with-symbol-versions and compare the names (not addresses or types) to foo.expsym. If there are any differences, they will be printed and the build will fail. foo.expsym should be sorted with `LANG=C sort -u'. This way, you can verify changes don't inadvertently add or remove symbols. If you do want to add (or, if you're bumping the major, remove) symbols, you can verify the changes and edit the foo.expsym file accordingly. This will also help to enforce rules about symbol changes on pullups in release branches. Note that using a version map (-Wl,--version-script=...) doesn't catch symbol removal -- ld quietly ignores symbols in the version map that aren't actually defined by any object in the library. So this supplements the version map. Proposed on tech-userlevel: https://mail-index.NetBSD.org/tech-userlevel/2024/03/16/msg014264.html --- share/mk/bsd.lib.mk | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/share/mk/bsd.lib.mk b/share/mk/bsd.lib.mk index 4db7809dda40..6edcf6b7e57a 100644 --- a/share/mk/bsd.lib.mk +++ b/share/mk/bsd.lib.mk @@ -1,4 +1,4 @@ -# $NetBSD: bsd.lib.mk,v 1.394 2023/06/03 21:24:57 lukem Exp $ +# $NetBSD: bsd.lib.mk,v 1.395 2024/03/20 13:50:37 riastradh Exp $ # @(#)bsd.lib.mk 8.3 (Berkeley) 4/22/94 .include @@ -648,6 +648,42 @@ ${_LIB.so.full}: ${_MAINLIBDEPS} ${HOST_LN} -sf ${_LIB.so.full} ${_LIB.so}.tmp ${MV} ${_LIB.so}.tmp ${_LIB.so} +# If there's a file listing expected symbols, fail if the diff from it +# to the actual symbols is nonempty, and show the diff in that case. +.if exists(${.CURDIR}/${LIB}.${MACHINE_ARCH}.expsym) +LIB_EXPSYM?= ${LIB}.${MACHINE_ARCH}.expsym +.elif exists(${.CURDIR}/${LIB}.expsym) +LIB_EXPSYM?= ${LIB}.expsym +.endif + +.if !empty(LIB_EXPSYM) +realall: ${_LIB.so.full}.diffsym +${_LIB.so.full}.diffsym: ${LIB_EXPSYM} ${_LIB.so.full}.actsym + ${_MKTARGET_CREATE} + if diff -u ${.ALLSRC} >${.TARGET}.tmp; then \ + ${MV} ${.TARGET}.tmp ${.TARGET}; \ + else \ + ret=$$?; \ + cat ${.TARGET}.tmp; \ + echo ${_LIB.so.full}: error: \ + actual symbols differ from expected symbols >&2; \ + exit $$ret; \ + fi +${_LIB.so.full}.actsym: ${_LIB.so.full} + ${_MKTARGET_CREATE} + ${NM} --dynamic --extern-only --defined-only --with-symbol-versions \ + ${_LIB.so.full} \ + | cut -d' ' -f3 | LANG=C sort -u >${.TARGET}.tmp + ${MV} ${.TARGET}.tmp ${.TARGET} +CLEANFILES+= ${_LIB.so.full}.actsym +CLEANFILES+= ${_LIB.so.full}.actsym.tmp +CLEANFILES+= ${_LIB.so.full}.diffsym +CLEANFILES+= ${_LIB.so.full}.diffsym.tmp +update-symbols: .PHONY +update-symbols: ${_LIB.so.full}.actsym + cp ${_LIB.so.full}.actsym ${.CURDIR}/${LIB}.expsym +.endif + .if !empty(LOBJS) # { LLIBS?= -lc ${_LIB.ln}: ${LOBJS}