36
36
# (glibc) GLIBC_2_11
37
37
#
38
38
MAX_VERSIONS = {
39
- 'GCC' : (4 ,4 ,0 ),
40
- 'CXXABI' : (1 ,3 ,3 ),
41
- 'GLIBCXX' : (3 ,4 ,13 ),
42
- 'GLIBC' : (2 ,11 )
39
+ 'GCC' : (4 ,4 ,0 ),
40
+ 'CXXABI' : (1 ,3 ,3 ),
41
+ 'GLIBCXX' : (3 ,4 ,13 ),
42
+ 'GLIBC' : (2 ,11 ),
43
+ 'LIBATOMIC' : (1 ,0 )
43
44
}
44
45
# See here for a description of _IO_stdin_used:
45
46
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=634261#109
46
47
47
48
# Ignore symbols that are exported as part of every executable
48
49
IGNORE_EXPORTS = {
49
- '_edata' , '_end' , '_init' , '__bss_start' , '_fini' , '_IO_stdin_used' , 'stdin' , 'stdout' , 'stderr'
50
+ '_edata' , '_end' , '__end__' , ' _init' , '__bss_start' , '__bss_start__' , '_bss_end__' , '__bss_end__ ' , '_fini' , '_IO_stdin_used' , 'stdin' , 'stdout' , 'stderr'
50
51
}
51
52
READELF_CMD = os .getenv ('READELF' , '/usr/bin/readelf' )
52
53
CPPFILT_CMD = os .getenv ('CPPFILT' , '/usr/bin/c++filt' )
59
60
'libanl.so.1' , # DNS resolve
60
61
'libm.so.6' , # math library
61
62
'librt.so.1' , # real-time (clock)
63
+ 'libatomic.so.1' ,
62
64
'ld-linux-x86-64.so.2' , # 64-bit dynamic linker
63
65
'ld-linux.so.2' , # 32-bit dynamic linker
66
+ 'ld-linux-aarch64.so.1' , # 64-bit ARM dynamic linker
67
+ 'ld-linux-armhf.so.3' , # 32-bit ARM dynamic linker
68
+ 'ld-linux-riscv64-lp64d.so.1' , # 64-bit RISC-V dynamic linker
64
69
# bitcoin-qt only
65
70
'libX11-xcb.so.1' , # part of X11
66
71
'libX11.so.6' , # part of X11
69
74
'libfreetype.so.6' , # font parsing
70
75
'libdl.so.2' # programming interface to dynamic linker
71
76
}
72
-
77
+ ARCH_MIN_GLIBC_VER = {
78
+ '80386' : (2 ,1 ),
79
+ 'X86-64' : (2 ,2 ,5 ),
80
+ 'ARM' : (2 ,4 ),
81
+ 'AArch64' :(2 ,17 ),
82
+ 'RISC-V' : (2 ,27 )
83
+ }
73
84
class CPPFilt (object ):
74
85
'''
75
86
Demangle C++ symbol names.
@@ -94,23 +105,25 @@ def read_symbols(executable, imports=True):
94
105
Parse an ELF executable and return a list of (symbol,version) tuples
95
106
for dynamic, imported symbols.
96
107
'''
97
- p = subprocess .Popen ([READELF_CMD , '--dyn-syms' , '-W' , executable ], stdout = subprocess .PIPE , stderr = subprocess .PIPE , stdin = subprocess .PIPE , universal_newlines = True )
108
+ p = subprocess .Popen ([READELF_CMD , '--dyn-syms' , '-W' , '-h' , executable ], stdout = subprocess .PIPE , stderr = subprocess .PIPE , stdin = subprocess .PIPE , universal_newlines = True )
98
109
(stdout , stderr ) = p .communicate ()
99
110
if p .returncode :
100
111
raise IOError ('Could not read symbols for %s: %s' % (executable , stderr .strip ()))
101
112
syms = []
102
113
for line in stdout .splitlines ():
103
114
line = line .split ()
115
+ if 'Machine:' in line :
116
+ arch = line [- 1 ]
104
117
if len (line )> 7 and re .match ('[0-9]+:$' , line [0 ]):
105
118
(sym , _ , version ) = line [7 ].partition ('@' )
106
119
is_import = line [6 ] == 'UND'
107
120
if version .startswith ('@' ):
108
121
version = version [1 :]
109
122
if is_import == imports :
110
- syms .append ((sym , version ))
123
+ syms .append ((sym , version , arch ))
111
124
return syms
112
125
113
- def check_version (max_versions , version ):
126
+ def check_version (max_versions , version , arch ):
114
127
if '_' in version :
115
128
(lib , _ , ver ) = version .rpartition ('_' )
116
129
else :
@@ -119,7 +132,7 @@ def check_version(max_versions, version):
119
132
ver = tuple ([int (x ) for x in ver .split ('.' )])
120
133
if not lib in max_versions :
121
134
return False
122
- return ver <= max_versions [lib ]
135
+ return ver <= max_versions [lib ] or lib == 'GLIBC' and ver <= ARCH_MIN_GLIBC_VER [ arch ]
123
136
124
137
def read_libraries (filename ):
125
138
p = subprocess .Popen ([READELF_CMD , '-d' , '-W' , filename ], stdout = subprocess .PIPE , stderr = subprocess .PIPE , stdin = subprocess .PIPE , universal_newlines = True )
@@ -142,16 +155,17 @@ def read_libraries(filename):
142
155
retval = 0
143
156
for filename in sys .argv [1 :]:
144
157
# Check imported symbols
145
- for sym ,version in read_symbols (filename , True ):
146
- if version and not check_version (MAX_VERSIONS , version ):
158
+ for sym ,version , arch in read_symbols (filename , True ):
159
+ if version and not check_version (MAX_VERSIONS , version , arch ):
147
160
print ('%s: symbol %s from unsupported version %s' % (filename , cppfilt (sym ), version ))
148
161
retval = 1
149
162
# Check exported symbols
150
- for sym ,version in read_symbols (filename , False ):
151
- if sym in IGNORE_EXPORTS :
152
- continue
153
- print ('%s: export of symbol %s not allowed' % (filename , cppfilt (sym )))
154
- retval = 1
163
+ if arch != 'RISC-V' :
164
+ for sym ,version ,arch in read_symbols (filename , False ):
165
+ if sym in IGNORE_EXPORTS :
166
+ continue
167
+ print ('%s: export of symbol %s not allowed' % (filename , cppfilt (sym )))
168
+ retval = 1
155
169
# Check dependency libraries
156
170
for library_name in read_libraries (filename ):
157
171
if library_name not in ALLOWED_LIBRARIES :
0 commit comments