diff options
Diffstat (limited to 'contrib/devtools')
-rw-r--r-- | contrib/devtools/README.md | 2 | ||||
-rwxr-xr-x | contrib/devtools/previous_release.sh | 149 | ||||
-rwxr-xr-x | contrib/devtools/symbol-check.py | 49 |
3 files changed, 196 insertions, 4 deletions
diff --git a/contrib/devtools/README.md b/contrib/devtools/README.md index 515a0d8fc6..f5533719c0 100644 --- a/contrib/devtools/README.md +++ b/contrib/devtools/README.md @@ -109,7 +109,7 @@ certain symbols and are only linked against allowed libraries. For Linux this means checking for allowed gcc, glibc and libstdc++ version symbols. This makes sure they are still compatible with the minimum supported distribution versions. -For macOS we check that the executables are only linked against libraries we allow. +For macOS and Windows we check that the executables are only linked against libraries we allow. Example usage after a gitian build: diff --git a/contrib/devtools/previous_release.sh b/contrib/devtools/previous_release.sh new file mode 100755 index 0000000000..efd035f778 --- /dev/null +++ b/contrib/devtools/previous_release.sh @@ -0,0 +1,149 @@ +#!/usr/bin/env bash +# +# Copyright (c) 2018-2019 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. +# +# Build previous releases. + +export LC_ALL=C + +CONFIG_FLAGS="" +FUNCTIONAL_TESTS=0 +DELETE_EXISTING=0 +USE_DEPENDS=0 +DOWNLOAD_BINARY=0 +CONFIG_FLAGS="" +TARGET="releases" + +while getopts ":hfrdbt:" opt; do + case $opt in + h) + echo "Usage: .previous_release.sh [options] tag1 tag2" + echo " options:" + echo " -h Print this message" + echo " -f Configure for functional tests" + echo " -r Remove existing directory" + echo " -d Use depends" + echo " -b Download release binary" + echo " -t Target directory (default: releases)" + exit 0 + ;; + f) + FUNCTIONAL_TESTS=1 + CONFIG_FLAGS="$CONFIG_FLAGS --without-gui --disable-tests --disable-bench" + ;; + r) + DELETE_EXISTING=1 + ;; + d) + USE_DEPENDS=1 + ;; + b) + DOWNLOAD_BINARY=1 + ;; + t) + TARGET=$OPTARG + ;; + \?) + echo "Invalid option: -$OPTARG" >&2 + exit 1 + ;; + esac +done + +shift $((OPTIND-1)) + +if [ -z "$1" ]; then + echo "Specify release tag(s), e.g.: .previous_release v0.15.1" + exit 1 +fi + +if [ ! -d "$TARGET" ]; then + mkdir -p $TARGET +fi + +if [ "$DOWNLOAD_BINARY" -eq "1" ]; then + HOST="${HOST:-$(./depends/config.guess)}" + case "$HOST" in + x86_64-*-linux*) + PLATFORM=x86_64-linux-gnu + ;; + x86_64-apple-darwin*) + PLATFORM=osx64 + ;; + *) + echo "Not sure which binary to download for $HOST." + exit 1 + ;; + esac +fi + +echo "Releases directory: $TARGET" +pushd "$TARGET" || exit 1 +{ + for tag in "$@" + do + if [ "$DELETE_EXISTING" -eq "1" ]; then + if [ -d "$tag" ]; then + rm -r "$tag" + fi + fi + + if [ "$DOWNLOAD_BINARY" -eq "0" ]; then + + if [ ! -d "$tag" ]; then + if [ -z $(git tag -l "$tag") ]; then + echo "Tag $tag not found" + exit 1 + fi + + git clone https://github.com/bitcoin/bitcoin "$tag" + pushd "$tag" || exit 1 + { + git checkout "$tag" + if [ "$USE_DEPENDS" -eq "1" ]; then + pushd depends || exit 1 + { + if [ "$FUNCTIONAL_TESTS" -eq "1" ]; then + make NO_QT=1 + else + make + fi + HOST="${HOST:-$(./config.guess)}" + } + popd || exit 1 + CONFIG_FLAGS="--prefix=$PWD/depends/$HOST $CONFIG_FLAGS" + fi + ./autogen.sh + ./configure $CONFIG_FLAGS + make + # Move binaries, so they're in the same place as in the release download: + mkdir bin + mv src/bitcoind src/bitcoin-cli src/bitcoin-tx bin + if [ "$FUNCTIONAL_TESTS" -eq "0" ]; then + mv src/qt/bitcoin-qt bin + fi + } + popd || exit 1 + fi + else + if [ -d "$tag" ]; then + echo "Using cached $tag" + else + mkdir "$tag" + if [[ "$tag" =~ v(.*)(rc[0-9]+)$ ]]; then + BIN_PATH="bin/bitcoin-core-${BASH_REMATCH[1]}/test.${BASH_REMATCH[2]}" + else + BIN_PATH="bin/bitcoin-core-${tag:1}" + fi + URL="https://bitcoin.org/$BIN_PATH/bitcoin-${tag:1}-$PLATFORM.tar.gz" + echo "Fetching: $URL" + curl -O $URL + tar -zxf "bitcoin-${tag:1}-$PLATFORM.tar.gz" -C "$tag" --strip-components=1 "bitcoin-${tag:1}" + rm "bitcoin-${tag:1}-$PLATFORM.tar.gz" + fi + fi + done +} +popd || exit 1 diff --git a/contrib/devtools/symbol-check.py b/contrib/devtools/symbol-check.py index f92d997621..6949cb7ced 100755 --- a/contrib/devtools/symbol-check.py +++ b/contrib/devtools/symbol-check.py @@ -3,9 +3,8 @@ # Distributed under the MIT 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 and glibc version symbols. This makes sure they are still compatible -with the minimum supported Linux distribution versions. +A script to check that the executables produced by gitian only contain +certain symbols and are only linked against allowed libraries. Example usage: @@ -53,6 +52,7 @@ IGNORE_EXPORTS = { } READELF_CMD = os.getenv('READELF', '/usr/bin/readelf') CPPFILT_CMD = os.getenv('CPPFILT', '/usr/bin/c++filt') +OBJDUMP_CMD = os.getenv('OBJDUMP', '/usr/bin/objdump') OTOOL_CMD = os.getenv('OTOOL', '/usr/bin/otool') # Allowed NEEDED libraries @@ -101,6 +101,26 @@ MACHO_ALLOWED_LIBRARIES = { 'libobjc.A.dylib', # Objective-C runtime library } +PE_ALLOWED_LIBRARIES = { +'ADVAPI32.dll', # security & registry +'IPHLPAPI.DLL', # IP helper API +'KERNEL32.dll', # win32 base APIs +'msvcrt.dll', # C standard library for MSVC +'SHELL32.dll', # shell API +'USER32.dll', # user interface +'WS2_32.dll', # sockets +# bitcoin-qt only +'dwmapi.dll', # desktop window manager +'GDI32.dll', # graphics device interface +'IMM32.dll', # input method editor +'ole32.dll', # component object model +'OLEAUT32.dll', # OLE Automation API +'SHLWAPI.dll', # light weight shell API +'UxTheme.dll', +'VERSION.dll', # version checking +'WINMM.dll', # WinMM audio API +} + class CPPFilt(object): ''' Demangle C++ symbol names. @@ -218,6 +238,26 @@ def check_MACHO_libraries(filename) -> bool: ok = False return ok +def pe_read_libraries(filename) -> List[str]: + p = subprocess.Popen([OBJDUMP_CMD, '-x', filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True) + (stdout, stderr) = p.communicate() + if p.returncode: + raise IOError('Error opening file') + libraries = [] + for line in stdout.splitlines(): + if 'DLL Name:' in line: + tokens = line.split(': ') + libraries.append(tokens[1]) + return libraries + +def check_PE_libraries(filename) -> bool: + ok = True + for dylib in pe_read_libraries(filename): + if dylib not in PE_ALLOWED_LIBRARIES: + print('{} is not in ALLOWED_LIBRARIES!'.format(dylib)) + ok = False + return ok + CHECKS = { 'ELF': [ ('IMPORTED_SYMBOLS', check_imported_symbols), @@ -226,6 +266,9 @@ CHECKS = { ], 'MACHO': [ ('DYNAMIC_LIBRARIES', check_MACHO_libraries) +], +'PE' : [ + ('DYNAMIC_LIBRARIES', check_PE_libraries) ] } |