Skip to content

Commit 6a97f72

Browse files
committed
Add contrib/symbol-check.py
1 parent 694ce8f commit 6a97f72

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

contrib/symbol-check.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2014 Wladimir J. van der Laan
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
'''
6+
A script to check that a secp256k1 shared library
7+
exports only expected symbols.
8+
9+
Example usage:
10+
11+
contrib/symbol-check.py .libs/libsecp256k1.so.0.0.0
12+
or
13+
contrib/symbol-check.py .libs/libsecp256k1-0.dll
14+
'''
15+
import re
16+
import sys
17+
import subprocess
18+
from typing import List
19+
20+
import lief #type:ignore
21+
22+
def grep_exported_symbols() -> List[str]:
23+
grep_output = subprocess.check_output(["git", "grep", "^SECP256K1_API", "--", "include"], universal_newlines=True, encoding="utf8")
24+
lines = grep_output.split("\n")
25+
exports: List[str] = []
26+
for line in lines:
27+
if line.strip():
28+
function_name = re.sub(r'\W', '', line.split(" ")[-1])
29+
exports.append(function_name)
30+
return exports
31+
32+
def check_ELF_exported_symbols(library, expected_exports) -> bool:
33+
ok: bool = True
34+
elf_lib: lief.ELF.Binary = library.concrete
35+
36+
for symbol in elf_lib.exported_symbols:
37+
name: str = symbol.name
38+
if name in expected_exports:
39+
continue
40+
print(f'{filename}: export of symbol {name} not expected')
41+
ok = False
42+
return ok
43+
44+
def check_PE_exported_functions(library, expected_exports) -> bool:
45+
ok: bool = True
46+
pe_lib: lief.PE.Binary = library.concrete
47+
48+
for function in pe_lib.exported_functions:
49+
name: str = function.name
50+
if name in expected_exports:
51+
continue
52+
print(f'{filename}: export of function {name} not expected')
53+
ok = False
54+
return ok
55+
56+
CHECKS = {
57+
lief.EXE_FORMATS.ELF: [
58+
('EXPORTED_SYMBOLS', check_ELF_exported_symbols),
59+
],
60+
lief.EXE_FORMATS.PE: [
61+
('EXPORTED_FUNCTIONS', check_PE_exported_functions),
62+
]
63+
}
64+
65+
USAGE = """
66+
symbol-check.py is a script to check that a secp256k1 shared library
67+
exports only expected symbols.
68+
69+
Usage:
70+
./contrib/symbol-check.py <library>
71+
72+
"""
73+
74+
if __name__ == '__main__':
75+
if len(sys.argv) != 2:
76+
sys.exit(USAGE)
77+
78+
filename: str = sys.argv[1]
79+
try:
80+
library: lief.Binary = lief.parse(filename)
81+
exe_format: lief.EXE_FORMATS = library.format
82+
if exe_format != lief.EXE_FORMATS.ELF and exe_format != lief.EXE_FORMATS.PE:
83+
print(f'{filename}: unsupported executable format, only ELF and PE formats are supported')
84+
sys.exit(1)
85+
86+
obj_type = library.abstract.header.object_type
87+
if obj_type != lief.OBJECT_TYPES.LIBRARY:
88+
print(f'{filename}: unsupported object type, only LIBRARY type is supported')
89+
sys.exit(1)
90+
91+
expected_exports = grep_exported_symbols()
92+
failed: List[str] = []
93+
for (name, func) in CHECKS[exe_format]:
94+
if not func(library, expected_exports):
95+
failed.append(name)
96+
if failed:
97+
print(f'{filename}: failed {" ".join(failed)}')
98+
sys.exit(1)
99+
except IOError:
100+
print(f'{filename}: cannot open')
101+
sys.exit(1)

0 commit comments

Comments
 (0)