libvboot_host: Check for undefined symbols

Check the library does not contain undefined vb2 symbols.

BUG=b:124141368, chromium:968464
BRANCH=none
TEST=Check the test pass with FEATURES=test emerge-brya vboot_reference
Revert crrev.com/c/5262229, observe errors:
...
libvboot_host: Unexpected undefined symbols:
vb2_fill_dev_boot_flags
vb2_gbb_read_recovery_key
vb2_secdata_fwmp_init
vb2_secdata_kernel_get
...
Error:
/tmp/portage/.../vboot_reference-9999/.../tests/vhost_reference.sh:
failed with exit code 1

Change-Id: I09bfcf7fa67de171ec581ff9feac48749d24ed41
Signed-off-by: Gwendal Grignou <gwendal@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/vboot_reference/+/5282761
Reviewed-by: Julius Werner <jwerner@chromium.org>
diff --git a/Makefile b/Makefile
index 455285e..3174b84 100644
--- a/Makefile
+++ b/Makefile
@@ -519,6 +519,10 @@
 HOSTLIB = ${BUILD}/libvboot_host.so
 HOSTLIB_STATIC = ${BUILD}/libvboot_host.a
 
+# For testing purposes files contianing some libvboot_host symbols.
+HOSTLIB_DEF = ${BUILD}/tests/libvboot_host_def.txt
+HOSTLIB_UNDEF = ${BUILD}/tests/libvboot_host_undef.txt
+
 HOSTLIB_SRCS = \
 	cgpt/cgpt_add.c \
 	cgpt/cgpt_boot.c \
@@ -988,9 +992,18 @@
 ${HOSTLIB}: ${HOSTLIB_OBJS}
 	@${PRINTF} "    RM            $(subst ${BUILD}/,,$@)\n"
 	${Q}rm -f $@
-	@${PRINTF} "    LD          $(subst ${BUILD}/,,$@)\n"
+	@${PRINTF} "    LD            $(subst ${BUILD}/,,$@)\n"
 	${Q}${LD} ${LDFLAGS} ${LDLIBS} -shared -Wl,-soname,$(subst ${BUILD}/,,$@) $^ -o $@
 
+${HOSTLIB_DEF}: ${HOSTLIB_STATIC}
+	@${PRINTF} "    NMd           $(subst ${BUILD}/,,$@)\n"
+	${Q}nm --defined-only --format=just-symbols $^ > $@
+
+${HOSTLIB_UNDEF}: ${HOSTLIB_STATIC}
+	@${PRINTF} "    NMu           $(subst ${BUILD}/,,$@)\n"
+	${Q}nm --undefined-only --format=just-symbols $^ > $@
+
+
 .PHONY: headers_install
 headers_install:
 	@${PRINTF} "    INSTALL       HEADERS\n"
@@ -1326,7 +1339,7 @@
 	${RUNTEST} ${BUILD_RUN}/tests/cgptlib_test
 
 .PHONY: runtestscripts
-runtestscripts: install_for_test
+runtestscripts: install_for_test ${HOSTLIB_DEF} ${HOSTLIB_UNDEF}
 	${RUNTEST} ${SRC_RUN}/scripts/image_signing/sign_android_unittests.sh
 	${RUNTEST} ${SRC_RUN}/scripts/image_signing/sign_uefi_unittest.py
 	${RUNTEST} ${SRC_RUN}/tests/load_kernel_tests.sh
@@ -1337,6 +1350,7 @@
 	${RUNTEST} ${SRC_RUN}/tests/run_vbutil_tests.sh
 	${RUNTEST} ${SRC_RUN}/tests/vb2_rsa_tests.sh
 	${RUNTEST} ${SRC_RUN}/tests/vb2_firmware_tests.sh
+	${RUNTEST} ${SRC_RUN}/tests/vhost_reference.sh ${HOSTLIB_DEF} ${HOSTLIB_UNDEF}
 
 .PHONY: runmisctests
 runmisctests: install_for_test
diff --git a/tests/vhost_reference.sh b/tests/vhost_reference.sh
new file mode 100755
index 0000000..c0ca4bf
--- /dev/null
+++ b/tests/vhost_reference.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+# Copyright 2024 The ChromiumOS Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# Load common constants and variables.
+. "$(dirname "$0")/common.sh"
+
+TMPD="$(mktemp -d /tmp/"$(basename "$0")".XXXXX)"
+trap '/bin/rm -rf "${TMPD}"' EXIT
+
+return_code=0
+
+main() {
+  local hostlib_def_symbols=$1
+  local hostlib_undef_symbols=$2
+  local never_def_vb2_functions="${TMPD}/vb2_undef.txt"
+
+  if [ ! -s "${hostlib_def_symbols}" ] || [ ! -s "${hostlib_undef_symbols}" ]; then
+    echo "Missing input data." >&2
+    exit 1
+  fi
+
+  # We should see any vb2 symbols undefined.
+  grep -vf "${hostlib_def_symbols}" "${hostlib_undef_symbols}" | \
+    grep vb2 > "${never_def_vb2_functions}"
+
+  if [ -s "${never_def_vb2_functions}" ]; then
+    echo "libvboot_host: Unexpected undefined symbols: " >&2
+    cat "${never_def_vb2_functions}" >&2
+    return_code=1
+  fi
+  return "${return_code}"
+}
+
+main "$@"