2"""Check that a libsecp256k1 shared library exports only expected symbols.
5 - When building with Autotools:
6 ./tools/symbol-check.py .libs/libsecp256k1.so
7 ./tools/symbol-check.py .libs/libsecp256k1-<V>.dll
8 ./tools/symbol-check.py .libs/libsecp256k1.dylib
10 - When building
with CMake:
11 ./tools/symbol-check.py build/lib/libsecp256k1.so
12 ./tools/symbol-check.py build/bin/libsecp256k1-<V>.dll
13 ./tools/symbol-check.py build/lib/libsecp256k1.dylib
"""
22class UnexpectedExport(RuntimeError):
27 """Adapter function to get exported symbols based on the library format."""
28 if library.format == lief.Binary.FORMATS.ELF:
29 return [symbol.name
for symbol
in library.exported_symbols]
30 elif library.format == lief.Binary.FORMATS.PE:
31 return [entry.name
for entry
in library.get_export().entries]
32 elif library.format == lief.Binary.FORMATS.MACHO:
33 return [symbol.name[1:]
for symbol
in library.exported_symbols]
34 raise NotImplementedError(f
"Unsupported format: {library.format}")
38 """Guess the list of expected exported symbols from the source code."""
39 grep_output = subprocess.check_output(
40 [
"git",
"grep",
r"^\s*SECP256K1_API",
"--",
"include"],
41 universal_newlines=
True,
44 lines = grep_output.split(
"\n")
45 pattern = re.compile(
r'\bsecp256k1_\w+')
46 exported: list[str] = [pattern.findall(line)[-1]
for line
in lines
if line.strip()]
51 """Check that the library exports only the expected symbols."""
53 unexpected_exports = set(actual_exports) - set(expected_exports)
54 if unexpected_exports != set():
58 if len(sys.argv) != 2:
61 library = lief.parse(sys.argv[1])
65 except UnexpectedExport
as e:
66 print(f
"{sys.argv[0]}: In {sys.argv[1]}: {e}")
71if __name__ ==
"__main__":
list[str] get_exported_exports(library)
list[str] grep_expected_symbols()
None check_symbols(library, expected_exports)