From a699d5eb53de551b81cd591b234741f8302a39bd Mon Sep 17 00:00:00 2001 From: Wade Carpenter Date: Thu, 23 Nov 2023 14:34:12 -0800 Subject: [PATCH] shared: add tests for shared library contents --- shared/BUILD.bazel | 21 ++++++++++++++- shared/check_symtab.py | 61 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100755 shared/check_symtab.py diff --git a/shared/BUILD.bazel b/shared/BUILD.bazel index e4477b0..109175b 100644 --- a/shared/BUILD.bazel +++ b/shared/BUILD.bazel @@ -22,7 +22,7 @@ cc_shared_library( ) assert_linking_test( - name = "check_libthree_so", + name = "check_libthree_linking", lib_root_name = "three", require = [ "libone.so", @@ -30,6 +30,25 @@ assert_linking_test( ], ) +py_test( + name = "check_libthree_dynsyms", + srcs = ["check_symtab.py"], + args = [ + "--sut", + "libthree.so", + "--undefined", + "_Z3onev", + "--undefined", + "_Z3twov", + "--defined", + "_Z5threev", + "--", + "$(locations :three_so)", + ], + data = [":three_so"], + main = "check_symtab.py", +) + # Expected to pass cc_test( name = "test1", diff --git a/shared/check_symtab.py b/shared/check_symtab.py new file mode 100755 index 0000000..65f1408 --- /dev/null +++ b/shared/check_symtab.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +from argparse import ArgumentParser +from collections.abc import Iterable +from os.path import basename +from re import split +from shlex import quote +from subprocess import check_output +from typing import Optional + + +def _fmt(v: Optional[Iterable[str]]) -> Optional[str]: + return ("\n " + "\n ".join(sorted(v))) if v else None + + +def assert_empty(entries: set[str], tag: str) -> None: + assert not entries, f"{tag} entries ({len(entries)}): {_fmt(entries)}" + + +def main(): + ap = ArgumentParser() + ap.add_argument("--sut") + ap.add_argument("--undefined", action="append") + ap.add_argument("--defined", action="append") + ap.add_argument("files", metavar="FILE", nargs="+") + args = ap.parse_args() + + sut = None + for fn in args.files: + if basename(fn) == args.sut: + sut = fn + break + + assert sut, f"SUT {args.sut} not found in files args {args.files}" + print("sut:", sut) + + cmd = ["readelf", "--dyn-syms", sut] + print("+", " ".join(map(quote, cmd))) + out = check_output(cmd, text=True) + defined = set() + undefined = set() + for line in out.splitlines(): + parts = split(r"\s+", line) + try: + defState = parts[7] + name = " ".join(parts[8:]) + except IndexError: + continue + if not name.strip(): + continue + if defState == "Ndx": + continue + (undefined if defState == "UND" else defined).add(name) + + print("undefined:", _fmt(undefined)) + print("defined:", _fmt(defined)) + + assert_empty(set(args.undefined) - undefined, "missing undefined") + assert_empty(set(args.defined) - defined, "missing defined") + + +main()