mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-20 02:25:40 +01:00
devtools: add script to check symbols from Linux gitian executables
Add a script to check that the (Linux) executables produced by gitian only contain allowed gcc, glibc and libstdc++ version symbols. This makes sure they are still compatible with the minimum supported Linux distribution versions.
This commit is contained in:
parent
4765b8c116
commit
74fc254c2b
@ -3,7 +3,7 @@ Contents
|
|||||||
This directory contains tools for developers working on this repository.
|
This directory contains tools for developers working on this repository.
|
||||||
|
|
||||||
github-merge.sh
|
github-merge.sh
|
||||||
----------------
|
==================
|
||||||
|
|
||||||
A small script to automate merging pull-requests securely and sign them with GPG.
|
A small script to automate merging pull-requests securely and sign them with GPG.
|
||||||
|
|
||||||
@ -36,7 +36,8 @@ Configuring the github-merge tool for the bitcoin repository is done in the foll
|
|||||||
git config githubmerge.testcmd "make -j4 check" (adapt to whatever you want to use for testing)
|
git config githubmerge.testcmd "make -j4 check" (adapt to whatever you want to use for testing)
|
||||||
git config --global user.signingkey mykeyid (if you want to GPG sign)
|
git config --global user.signingkey mykeyid (if you want to GPG sign)
|
||||||
|
|
||||||
## fix-copyright-headers.py
|
fix-copyright-headers.py
|
||||||
|
===========================
|
||||||
|
|
||||||
Every year newly updated files need to have its copyright headers updated to reflect the current year.
|
Every year newly updated files need to have its copyright headers updated to reflect the current year.
|
||||||
If you run this script from src/ it will automatically update the year on the copyright header for all
|
If you run this script from src/ it will automatically update the year on the copyright header for all
|
||||||
@ -46,4 +47,25 @@ For example a file changed in 2014 (with 2014 being the current year):
|
|||||||
```// Copyright (c) 2009-2013 The Bitcoin developers```
|
```// Copyright (c) 2009-2013 The Bitcoin developers```
|
||||||
|
|
||||||
would be changed to:
|
would be changed to:
|
||||||
```// Copyright (c) 2009-2014 The Bitcoin developers```
|
```// Copyright (c) 2009-2014 The Bitcoin developers```
|
||||||
|
|
||||||
|
symbol-check.py
|
||||||
|
==================
|
||||||
|
|
||||||
|
A script to check that the (Linux) executables produced by gitian only contain
|
||||||
|
allowed gcc, glibc and libstdc++ version symbols. This makes sure they are
|
||||||
|
still compatible with the minimum supported Linux distribution versions.
|
||||||
|
|
||||||
|
Example usage after a gitian build:
|
||||||
|
|
||||||
|
find ../gitian-builder/build -type f -executable | xargs python contrib/devtools/symbol-check.py
|
||||||
|
|
||||||
|
If only supported symbols are used the return value will be 0 and the output will be empty.
|
||||||
|
|
||||||
|
If there are 'unsupported' symbols, the return value will be 1 a list like this will be printed:
|
||||||
|
|
||||||
|
.../64/test_bitcoin: symbol memcpy from unsupported version GLIBC_2.14
|
||||||
|
.../64/test_bitcoin: symbol __fdelt_chk from unsupported version GLIBC_2.15
|
||||||
|
.../64/test_bitcoin: symbol std::out_of_range::~out_of_range() from unsupported version GLIBCXX_3.4.15
|
||||||
|
.../64/test_bitcoin: symbol _ZNSt8__detail15_List_nod from unsupported version GLIBCXX_3.4.15
|
||||||
|
|
||||||
|
108
contrib/devtools/symbol-check.py
Executable file
108
contrib/devtools/symbol-check.py
Executable file
@ -0,0 +1,108 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# Copyright (c) 2014 Wladimir J. van der Laan
|
||||||
|
# Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
'''
|
||||||
|
A script to check that the (Linux) executables produced by gitian only contain
|
||||||
|
allowed gcc, glibc and libstdc++ version symbols. This makes sure they are
|
||||||
|
still compatible with the minimum supported Linux distribution versions.
|
||||||
|
|
||||||
|
Example usage:
|
||||||
|
|
||||||
|
find ../gitian-builder/build -type f -executable | xargs python contrib/devtools/symbol-check.py
|
||||||
|
'''
|
||||||
|
from __future__ import division, print_function
|
||||||
|
import subprocess
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Debian 6.0.9 (Squeeze) has:
|
||||||
|
#
|
||||||
|
# - g++ version 4.4.5 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=g%2B%2B)
|
||||||
|
# - libc version 2.11.3 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=libc6)
|
||||||
|
# - libstdc++ version 4.4.5 (https://packages.debian.org/search?suite=default§ion=all&arch=any&searchon=names&keywords=libstdc%2B%2B6)
|
||||||
|
#
|
||||||
|
# Ubuntu 10.04.4 (Lucid Lynx) has:
|
||||||
|
#
|
||||||
|
# - g++ version 4.4.3 (http://packages.ubuntu.com/search?keywords=g%2B%2B&searchon=names&suite=lucid§ion=all)
|
||||||
|
# - libc version 2.11.1 (http://packages.ubuntu.com/search?keywords=libc6&searchon=names&suite=lucid§ion=all)
|
||||||
|
# - libstdc++ version 4.4.3 (http://packages.ubuntu.com/search?suite=lucid§ion=all&arch=any&keywords=libstdc%2B%2B&searchon=names)
|
||||||
|
#
|
||||||
|
# Taking the minimum of these as our target.
|
||||||
|
#
|
||||||
|
# According to GNU ABI document (http://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html) this corresponds to:
|
||||||
|
# GCC 4.4.0: GCC_4.4.0
|
||||||
|
# GCC 4.4.2: GLIBCXX_3.4.13, CXXABI_1.3.3
|
||||||
|
# (glibc) GLIBC_2_11
|
||||||
|
#
|
||||||
|
MAX_VERSIONS = {
|
||||||
|
'GCC': (4,4,0),
|
||||||
|
'CXXABI': (1,3,3),
|
||||||
|
'GLIBCXX': (3,4,13),
|
||||||
|
'GLIBC': (2,11)
|
||||||
|
}
|
||||||
|
READELF_CMD = '/usr/bin/readelf'
|
||||||
|
CPPFILT_CMD = '/usr/bin/c++filt'
|
||||||
|
|
||||||
|
class CPPFilt(object):
|
||||||
|
'''
|
||||||
|
Demangle C++ symbol names.
|
||||||
|
|
||||||
|
Use a pipe to the 'c++filt' command.
|
||||||
|
'''
|
||||||
|
def __init__(self):
|
||||||
|
self.proc = subprocess.Popen(CPPFILT_CMD, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
def __call__(self, mangled):
|
||||||
|
self.proc.stdin.write(mangled + '\n')
|
||||||
|
return self.proc.stdout.readline().rstrip()
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
self.proc.stdin.close()
|
||||||
|
self.proc.stdout.close()
|
||||||
|
self.proc.wait()
|
||||||
|
|
||||||
|
def read_symbols(executable, imports=True):
|
||||||
|
'''
|
||||||
|
Parse an ELF executable and return a list of (symbol,version) tuples
|
||||||
|
for dynamic, imported symbols.
|
||||||
|
'''
|
||||||
|
p = subprocess.Popen([READELF_CMD, '--dyn-syms', '-W', executable], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
|
||||||
|
(stdout, stderr) = p.communicate()
|
||||||
|
if p.returncode:
|
||||||
|
raise IOError('Could not read symbols for %s: %s' % (executable, stderr.strip()))
|
||||||
|
syms = []
|
||||||
|
for line in stdout.split('\n'):
|
||||||
|
line = line.split()
|
||||||
|
if len(line)>7 and re.match('[0-9]+:$', line[0]):
|
||||||
|
(sym, _, version) = line[7].partition('@')
|
||||||
|
is_import = line[6] == 'UND'
|
||||||
|
if version.startswith('@'):
|
||||||
|
version = version[1:]
|
||||||
|
if is_import == imports:
|
||||||
|
syms.append((sym, version))
|
||||||
|
return syms
|
||||||
|
|
||||||
|
def check_version(max_versions, version):
|
||||||
|
if '_' in version:
|
||||||
|
(lib, _, ver) = version.rpartition('_')
|
||||||
|
else:
|
||||||
|
lib = version
|
||||||
|
ver = '0'
|
||||||
|
ver = tuple([int(x) for x in ver.split('.')])
|
||||||
|
if not lib in max_versions:
|
||||||
|
return False
|
||||||
|
return ver <= max_versions[lib]
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
cppfilt = CPPFilt()
|
||||||
|
retval = 0
|
||||||
|
for filename in sys.argv[1:]:
|
||||||
|
for sym,version in read_symbols(filename, True):
|
||||||
|
if version and not check_version(MAX_VERSIONS, version):
|
||||||
|
print('%s: symbol %s from unsupported version %s' % (filename, cppfilt(sym), version))
|
||||||
|
retval = 1
|
||||||
|
|
||||||
|
exit(retval)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user