1010
1111 find ../path/to/binaries -type f -executable | xargs python3 contrib/devtools/symbol-check.py
1212'''
13- import subprocess
1413import sys
1514from typing import List , Optional
1615
1716import lief
18- import pixie
1917
20- from utils import determine_wellknown_cmd
18+ # temporary constant, to be replaced with lief.ELF.ARCH.RISCV
19+ # https://github.com/lief-project/LIEF/pull/562
20+ LIEF_ELF_ARCH_RISCV = lief .ELF .ARCH (243 )
2121
2222# Debian 8 (Jessie) EOL: 2020. https://wiki.debian.org/DebianReleases#Production_Releases
2323#
4343MAX_VERSIONS = {
4444'GCC' : (4 ,8 ,0 ),
4545'GLIBC' : {
46- pixie . EM_386 : (2 ,17 ),
47- pixie . EM_X86_64 : (2 ,17 ),
48- pixie . EM_ARM : (2 ,17 ),
49- pixie . EM_AARCH64 :(2 ,17 ),
50- pixie . EM_PPC64 : (2 ,17 ),
51- pixie . EM_RISCV : (2 ,27 ),
46+ lief . ELF . ARCH . i386 : (2 ,17 ),
47+ lief . ELF . ARCH . x86_64 : (2 ,17 ),
48+ lief . ELF . ARCH . ARM : (2 ,17 ),
49+ lief . ELF . ARCH . AARCH64 :(2 ,17 ),
50+ lief . ELF . ARCH . PPC64 : (2 ,17 ),
51+ LIEF_ELF_ARCH_RISCV : (2 ,27 ),
5252},
5353'LIBATOMIC' : (1 ,0 ),
5454'V' : (0 ,5 ,0 ), # xkb (bitcoin-qt only)
5858
5959# Ignore symbols that are exported as part of every executable
6060IGNORE_EXPORTS = {
61- '_edata' , '_end' , '__end__' , '_init' , '__bss_start' , '__bss_start__' , '_bss_end__' , '__bss_end__' , '_fini' , '_IO_stdin_used' , 'stdin' , 'stdout' , 'stderr' ,
61+ '_edata' , '_end' , '__end__' , '_init' , '__bss_start' , '__bss_start__' , '_bss_end__' ,
62+ '__bss_end__' , '_fini' , '_IO_stdin_used' , 'stdin' , 'stdout' , 'stderr' ,
6263'environ' , '_environ' , '__environ' ,
6364}
6465
133134'WTSAPI32.dll' ,
134135}
135136
136- class CPPFilt (object ):
137- '''
138- Demangle C++ symbol names.
139-
140- Use a pipe to the 'c++filt' command.
141- '''
142- def __init__ (self ):
143- self .proc = subprocess .Popen (determine_wellknown_cmd ('CPPFILT' , 'c++filt' ), stdin = subprocess .PIPE , stdout = subprocess .PIPE , universal_newlines = True )
144-
145- def __call__ (self , mangled ):
146- self .proc .stdin .write (mangled + '\n ' )
147- self .proc .stdin .flush ()
148- return self .proc .stdout .readline ().rstrip ()
149-
150- def close (self ):
151- self .proc .stdin .close ()
152- self .proc .stdout .close ()
153- self .proc .wait ()
154-
155137def check_version (max_versions , version , arch ) -> bool :
156- if '_' in version :
157- (lib , _ , ver ) = version .rpartition ('_' )
158- else :
159- lib = version
160- ver = '0'
138+ (lib , _ , ver ) = version .rpartition ('_' )
161139 ver = tuple ([int (x ) for x in ver .split ('.' )])
162140 if not lib in max_versions :
163141 return False
@@ -167,41 +145,42 @@ def check_version(max_versions, version, arch) -> bool:
167145 return ver <= max_versions [lib ][arch ]
168146
169147def check_imported_symbols (filename ) -> bool :
170- elf = pixie .load (filename )
171- cppfilt = CPPFilt ()
172148 ok : bool = True
149+ binary = lief .parse (filename )
173150
174- for symbol in elf . dyn_symbols :
175- if not symbol .is_import :
151+ for symbol in binary . imported_symbols :
152+ if not symbol .imported :
176153 continue
177- sym = symbol .name .decode ()
178- version = symbol .version .decode () if symbol .version is not None else None
179- if version and not check_version (MAX_VERSIONS , version , elf .hdr .e_machine ):
180- print ('{}: symbol {} from unsupported version {}' .format (filename , cppfilt (sym ), version ))
181- ok = False
154+
155+ version = symbol .symbol_version if symbol .has_version else None
156+
157+ if version :
158+ aux_version = version .symbol_version_auxiliary .name if version .has_auxiliary_version else None
159+ if aux_version and not check_version (MAX_VERSIONS , aux_version , binary .header .machine_type ):
160+ print (f'{ filename } : symbol { symbol .name } from unsupported version { version } ' )
161+ ok = False
182162 return ok
183163
184164def check_exported_symbols (filename ) -> bool :
185- elf = pixie .load (filename )
186- cppfilt = CPPFilt ()
187165 ok : bool = True
188- for symbol in elf .dyn_symbols :
189- if not symbol .is_export :
166+ binary = lief .parse (filename )
167+
168+ for symbol in binary .dynamic_symbols :
169+ if not symbol .exported :
190170 continue
191- sym = symbol .name . decode ()
192- if elf . hdr . e_machine == pixie . EM_RISCV or sym in IGNORE_EXPORTS :
171+ name = symbol .name
172+ if binary . header . machine_type == LIEF_ELF_ARCH_RISCV or name in IGNORE_EXPORTS :
193173 continue
194- print ('{ }: export of symbol {} not allowed' . format ( filename , cppfilt ( sym )) )
174+ print (f' { filename } : export of symbol { name } not allowed!' )
195175 ok = False
196176 return ok
197177
198178def check_ELF_libraries (filename ) -> bool :
199179 ok : bool = True
200- elf = pixie .load (filename )
201- for library_name in elf .query_dyn_tags (pixie .DT_NEEDED ):
202- assert (isinstance (library_name , bytes ))
203- if library_name .decode () not in ELF_ALLOWED_LIBRARIES :
204- print ('{}: NEEDED library {} is not allowed' .format (filename , library_name .decode ()))
180+ binary = lief .parse (filename )
181+ for library in binary .libraries :
182+ if library not in ELF_ALLOWED_LIBRARIES :
183+ print (f'{ filename } : { library } is not in ALLOWED_LIBRARIES!' )
205184 ok = False
206185 return ok
207186
0 commit comments