2022-12-28 12:22:14 +01:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
# Copyright (c) 2020 The Bitcoin Core developers
|
|
|
|
# Distributed under the MIT software license, see the accompanying
|
|
|
|
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
'''
|
|
|
|
Test script for symbol-check.py
|
|
|
|
'''
|
|
|
|
import subprocess
|
|
|
|
import unittest
|
|
|
|
|
|
|
|
def call_symbol_check(cc, source, executable, options):
|
|
|
|
subprocess.run([cc,source,'-o',executable] + options, check=True)
|
|
|
|
p = subprocess.run(['./contrib/devtools/symbol-check.py',executable], stdout=subprocess.PIPE, universal_newlines=True)
|
|
|
|
return (p.returncode, p.stdout.rstrip())
|
|
|
|
|
|
|
|
def get_machine(cc):
|
|
|
|
p = subprocess.run([cc,'-dumpmachine'], stdout=subprocess.PIPE, universal_newlines=True)
|
|
|
|
return p.stdout.rstrip()
|
|
|
|
|
|
|
|
class TestSymbolChecks(unittest.TestCase):
|
|
|
|
def test_ELF(self):
|
|
|
|
source = 'test1.c'
|
|
|
|
executable = 'test1'
|
|
|
|
cc = 'gcc'
|
|
|
|
|
|
|
|
# there's no way to do this test for RISC-V at the moment; bionic's libc is 2.27
|
|
|
|
# and we allow all symbols from 2.27.
|
|
|
|
if 'riscv' in get_machine(cc):
|
|
|
|
self.skipTest("test not available for RISC-V")
|
|
|
|
|
|
|
|
# memfd_create was introduced in GLIBC 2.27, so is newer than the upper limit of
|
|
|
|
# all but RISC-V but still available on bionic
|
|
|
|
with open(source, 'w', encoding="utf8") as f:
|
|
|
|
f.write('''
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include <sys/mman.h>
|
|
|
|
|
|
|
|
int memfd_create(const char *name, unsigned int flags);
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
memfd_create("test", 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
''')
|
|
|
|
|
|
|
|
self.assertEqual(call_symbol_check(cc, source, executable, []),
|
|
|
|
(1, executable + ': symbol memfd_create from unsupported version GLIBC_2.27\n' +
|
|
|
|
executable + ': failed IMPORTED_SYMBOLS'))
|
|
|
|
|
|
|
|
# -lutil is part of the libc6 package so a safe bet that it's installed
|
|
|
|
# it's also out of context enough that it's unlikely to ever become a real dependency
|
|
|
|
source = 'test2.c'
|
|
|
|
executable = 'test2'
|
|
|
|
with open(source, 'w', encoding="utf8") as f:
|
|
|
|
f.write('''
|
|
|
|
#include <utmp.h>
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
login(0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
''')
|
|
|
|
|
|
|
|
self.assertEqual(call_symbol_check(cc, source, executable, ['-lutil']),
|
|
|
|
(1, executable + ': NEEDED library libutil.so.1 is not allowed\n' +
|
|
|
|
executable + ': failed LIBRARY_DEPENDENCIES'))
|
|
|
|
|
Merge bitcoin/bitcoin#22645: scripts: prevent GCC optimising test symbols in test-symbol-check
5449d44e37982fcd5251fd47873c5f7d34c39fc9 scripts: prevent GCC optimising test symbols in test-symbol-check (fanquake)
Pull request description:
I noticed in #22381 that when the test-symbol-check target was being built with Clang and run in the CI it would fail due to using a too-new version of `pow` (used [here](https://github.com/bitcoin/bitcoin/blob/d67330d11245b11fbdd5e2dd5343ee451186931e/contrib/devtools/test-symbol-check.py#L85)). Our CIs use Focal (glibc 2.31) and the version of `pow` was the optimized version introduced in [glibc 2.29](https://lwn.net/Articles/778286/):
```bash
* Optimized generic exp, exp2, log, log2, pow, sinf, cosf, sincosf and tanf.
```
This made sense, except for that if it was failing when built using Clang, why hadn't it also been failing when being built with GCC?
Turns out GCC is optimizing away that call to `pow` at all optimization levels, including `-O0`, see: https://godbolt.org/z/53MhzMxT7, and this has been the case forever, or at least since GCC 5.x. Clang on the other hand, will only optimize away the `pow` call at `-O1` and `-O2`, not `-O0`: https://godbolt.org/z/Wbnqj3q6c. Thus when this test was built with Clang (we don't pass `-O` so we default to `-O0`) it was failing in the CI environment, because it would actually have a call to the "new" `pow`.
Avoid this issue by using a symbol that won't be optimized away, or that we are unlikely to ever have versioning issues with.
ACKs for top commit:
laanwj:
ACK 5449d44e37982fcd5251fd47873c5f7d34c39fc9
Tree-SHA512: 3a26c5c3a5f2905fd0dd90892470e241ba625c0af3be2629d06d5da3a97534c1d6a55b796bbdd41e2e6a26a8fab7d981b98c45d4238565b0eb7edf3c5da02007
2021-08-18 17:16:02 +02:00
|
|
|
# finally, check a simple conforming binary
|
2022-12-28 12:22:14 +01:00
|
|
|
source = 'test3.c'
|
|
|
|
executable = 'test3'
|
|
|
|
with open(source, 'w', encoding="utf8") as f:
|
|
|
|
f.write('''
|
Merge bitcoin/bitcoin#22645: scripts: prevent GCC optimising test symbols in test-symbol-check
5449d44e37982fcd5251fd47873c5f7d34c39fc9 scripts: prevent GCC optimising test symbols in test-symbol-check (fanquake)
Pull request description:
I noticed in #22381 that when the test-symbol-check target was being built with Clang and run in the CI it would fail due to using a too-new version of `pow` (used [here](https://github.com/bitcoin/bitcoin/blob/d67330d11245b11fbdd5e2dd5343ee451186931e/contrib/devtools/test-symbol-check.py#L85)). Our CIs use Focal (glibc 2.31) and the version of `pow` was the optimized version introduced in [glibc 2.29](https://lwn.net/Articles/778286/):
```bash
* Optimized generic exp, exp2, log, log2, pow, sinf, cosf, sincosf and tanf.
```
This made sense, except for that if it was failing when built using Clang, why hadn't it also been failing when being built with GCC?
Turns out GCC is optimizing away that call to `pow` at all optimization levels, including `-O0`, see: https://godbolt.org/z/53MhzMxT7, and this has been the case forever, or at least since GCC 5.x. Clang on the other hand, will only optimize away the `pow` call at `-O1` and `-O2`, not `-O0`: https://godbolt.org/z/Wbnqj3q6c. Thus when this test was built with Clang (we don't pass `-O` so we default to `-O0`) it was failing in the CI environment, because it would actually have a call to the "new" `pow`.
Avoid this issue by using a symbol that won't be optimized away, or that we are unlikely to ever have versioning issues with.
ACKs for top commit:
laanwj:
ACK 5449d44e37982fcd5251fd47873c5f7d34c39fc9
Tree-SHA512: 3a26c5c3a5f2905fd0dd90892470e241ba625c0af3be2629d06d5da3a97534c1d6a55b796bbdd41e2e6a26a8fab7d981b98c45d4238565b0eb7edf3c5da02007
2021-08-18 17:16:02 +02:00
|
|
|
#include <stdio.h>
|
2022-12-28 12:22:14 +01:00
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
Merge bitcoin/bitcoin#22645: scripts: prevent GCC optimising test symbols in test-symbol-check
5449d44e37982fcd5251fd47873c5f7d34c39fc9 scripts: prevent GCC optimising test symbols in test-symbol-check (fanquake)
Pull request description:
I noticed in #22381 that when the test-symbol-check target was being built with Clang and run in the CI it would fail due to using a too-new version of `pow` (used [here](https://github.com/bitcoin/bitcoin/blob/d67330d11245b11fbdd5e2dd5343ee451186931e/contrib/devtools/test-symbol-check.py#L85)). Our CIs use Focal (glibc 2.31) and the version of `pow` was the optimized version introduced in [glibc 2.29](https://lwn.net/Articles/778286/):
```bash
* Optimized generic exp, exp2, log, log2, pow, sinf, cosf, sincosf and tanf.
```
This made sense, except for that if it was failing when built using Clang, why hadn't it also been failing when being built with GCC?
Turns out GCC is optimizing away that call to `pow` at all optimization levels, including `-O0`, see: https://godbolt.org/z/53MhzMxT7, and this has been the case forever, or at least since GCC 5.x. Clang on the other hand, will only optimize away the `pow` call at `-O1` and `-O2`, not `-O0`: https://godbolt.org/z/Wbnqj3q6c. Thus when this test was built with Clang (we don't pass `-O` so we default to `-O0`) it was failing in the CI environment, because it would actually have a call to the "new" `pow`.
Avoid this issue by using a symbol that won't be optimized away, or that we are unlikely to ever have versioning issues with.
ACKs for top commit:
laanwj:
ACK 5449d44e37982fcd5251fd47873c5f7d34c39fc9
Tree-SHA512: 3a26c5c3a5f2905fd0dd90892470e241ba625c0af3be2629d06d5da3a97534c1d6a55b796bbdd41e2e6a26a8fab7d981b98c45d4238565b0eb7edf3c5da02007
2021-08-18 17:16:02 +02:00
|
|
|
printf("42");
|
|
|
|
return 0;
|
2022-12-28 12:22:14 +01:00
|
|
|
}
|
|
|
|
''')
|
|
|
|
|
Merge bitcoin/bitcoin#22645: scripts: prevent GCC optimising test symbols in test-symbol-check
5449d44e37982fcd5251fd47873c5f7d34c39fc9 scripts: prevent GCC optimising test symbols in test-symbol-check (fanquake)
Pull request description:
I noticed in #22381 that when the test-symbol-check target was being built with Clang and run in the CI it would fail due to using a too-new version of `pow` (used [here](https://github.com/bitcoin/bitcoin/blob/d67330d11245b11fbdd5e2dd5343ee451186931e/contrib/devtools/test-symbol-check.py#L85)). Our CIs use Focal (glibc 2.31) and the version of `pow` was the optimized version introduced in [glibc 2.29](https://lwn.net/Articles/778286/):
```bash
* Optimized generic exp, exp2, log, log2, pow, sinf, cosf, sincosf and tanf.
```
This made sense, except for that if it was failing when built using Clang, why hadn't it also been failing when being built with GCC?
Turns out GCC is optimizing away that call to `pow` at all optimization levels, including `-O0`, see: https://godbolt.org/z/53MhzMxT7, and this has been the case forever, or at least since GCC 5.x. Clang on the other hand, will only optimize away the `pow` call at `-O1` and `-O2`, not `-O0`: https://godbolt.org/z/Wbnqj3q6c. Thus when this test was built with Clang (we don't pass `-O` so we default to `-O0`) it was failing in the CI environment, because it would actually have a call to the "new" `pow`.
Avoid this issue by using a symbol that won't be optimized away, or that we are unlikely to ever have versioning issues with.
ACKs for top commit:
laanwj:
ACK 5449d44e37982fcd5251fd47873c5f7d34c39fc9
Tree-SHA512: 3a26c5c3a5f2905fd0dd90892470e241ba625c0af3be2629d06d5da3a97534c1d6a55b796bbdd41e2e6a26a8fab7d981b98c45d4238565b0eb7edf3c5da02007
2021-08-18 17:16:02 +02:00
|
|
|
self.assertEqual(call_symbol_check(cc, source, executable, []),
|
2022-12-28 12:22:14 +01:00
|
|
|
(0, ''))
|
|
|
|
|
|
|
|
def test_MACHO(self):
|
|
|
|
source = 'test1.c'
|
|
|
|
executable = 'test1'
|
|
|
|
cc = 'clang'
|
|
|
|
|
|
|
|
with open(source, 'w', encoding="utf8") as f:
|
|
|
|
f.write('''
|
|
|
|
#include <expat.h>
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
XML_ExpatVersion();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
''')
|
|
|
|
|
|
|
|
self.assertEqual(call_symbol_check(cc, source, executable, ['-lexpat']),
|
|
|
|
(1, 'libexpat.1.dylib is not in ALLOWED_LIBRARIES!\n' +
|
2023-05-13 17:32:47 +02:00
|
|
|
f'{executable}: failed DYNAMIC_LIBRARIES MIN_OS SDK'))
|
2022-12-28 12:22:14 +01:00
|
|
|
|
|
|
|
source = 'test2.c'
|
|
|
|
executable = 'test2'
|
|
|
|
with open(source, 'w', encoding="utf8") as f:
|
|
|
|
f.write('''
|
|
|
|
#include <CoreGraphics/CoreGraphics.h>
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
CGMainDisplayID();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
''')
|
|
|
|
|
|
|
|
self.assertEqual(call_symbol_check(cc, source, executable, ['-framework', 'CoreGraphics']),
|
2023-05-13 17:32:47 +02:00
|
|
|
(1, f'{executable}: failed MIN_OS SDK'))
|
|
|
|
|
|
|
|
source = 'test3.c'
|
|
|
|
executable = 'test3'
|
|
|
|
with open(source, 'w', encoding="utf8") as f:
|
|
|
|
f.write('''
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
''')
|
|
|
|
|
|
|
|
self.assertEqual(call_symbol_check(cc, source, executable, ['-mmacosx-version-min=10.14']),
|
|
|
|
(1, f'{executable}: failed SDK'))
|
2022-12-28 12:22:14 +01:00
|
|
|
|
2020-12-09 15:33:31 +01:00
|
|
|
def test_PE(self):
|
|
|
|
source = 'test1.c'
|
|
|
|
executable = 'test1.exe'
|
|
|
|
cc = 'x86_64-w64-mingw32-gcc'
|
|
|
|
|
|
|
|
with open(source, 'w', encoding="utf8") as f:
|
|
|
|
f.write('''
|
|
|
|
#include <pdh.h>
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
PdhConnectMachineA(NULL);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
''')
|
|
|
|
|
2023-05-13 17:32:47 +02:00
|
|
|
self.assertEqual(call_symbol_check(cc, source, executable, ['-lpdh', '-Wl,--major-subsystem-version', '-Wl,6', '-Wl,--minor-subsystem-version', '-Wl,1']),
|
2020-12-09 15:33:31 +01:00
|
|
|
(1, 'pdh.dll is not in ALLOWED_LIBRARIES!\n' +
|
|
|
|
executable + ': failed DYNAMIC_LIBRARIES'))
|
|
|
|
|
|
|
|
source = 'test2.c'
|
|
|
|
executable = 'test2.exe'
|
2023-05-13 17:32:47 +02:00
|
|
|
|
|
|
|
with open(source, 'w', encoding="utf8") as f:
|
|
|
|
f.write('''
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
''')
|
|
|
|
|
|
|
|
self.assertEqual(call_symbol_check(cc, source, executable, ['-Wl,--major-subsystem-version', '-Wl,9', '-Wl,--minor-subsystem-version', '-Wl,9']),
|
|
|
|
(1, executable + ': failed SUBSYSTEM_VERSION'))
|
|
|
|
|
|
|
|
source = 'test3.c'
|
|
|
|
executable = 'test3.exe'
|
2020-12-09 15:33:31 +01:00
|
|
|
with open(source, 'w', encoding="utf8") as f:
|
|
|
|
f.write('''
|
|
|
|
#include <windows.h>
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
CoFreeUnusedLibrariesEx(0,0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
''')
|
|
|
|
|
2023-05-13 17:32:47 +02:00
|
|
|
self.assertEqual(call_symbol_check(cc, source, executable, ['-lole32', '-Wl,--major-subsystem-version', '-Wl,6', '-Wl,--minor-subsystem-version', '-Wl,1']),
|
2020-12-09 15:33:31 +01:00
|
|
|
(0, ''))
|
|
|
|
|
|
|
|
|
2022-12-28 12:22:14 +01:00
|
|
|
if __name__ == '__main__':
|
|
|
|
unittest.main()
|
|
|
|
|