File: check_freestanding_dependencies.py

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (119 lines) | stat: -rwxr-xr-x 4,786 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python3
#
# This source file is part of the Swift.org open source project
#
# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See https://swift.org/LICENSE.txt for license information
# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors

import argparse
import subprocess
import sys

parser = argparse.ArgumentParser()
parser.add_argument("--library", help="path to libswiftCore.a to check")
parser.add_argument("--vendor", help="flavor of the freestanding stdlib")
parser.add_argument("--nm-path", help="path to llvm-nm binary to use")
args = parser.parse_args()


################################################################################
#
# EXPECTED/ALLOWED DEPENDENCIES
#
# Before adding new symbols into these lists please consult with:
# @kubamracek, @compnerd
#
# The 'freestanding' build of the Swift runtime and standard library is
# intended to depend on as few platform symbols/APIs as possible.
#
################################################################################
cxx_dependencies = [
    "___cxa_guard_acquire", "___cxa_guard_release",
]
math_dependencies = [
    "_ceill", "_cos", "_cosf", "_cosl", "_exp", "_exp2", "_exp2f", "_exp2l",
    "_expf", "_expl", "_floorl", "_fma", "_fmaf", "_fmal", "_fmod", "_fmodf",
    "_fmodl", "_log", "_log10", "_log10f", "_log10l", "_log2", "_log2f",
    "_log2l", "_logf", "_logl", "_nearbyintl", "_remainder", "_remainderf",
    "_remainderl", "_rintl", "_roundl", "_sin", "_sinf", "_sinl", "_truncl",
]
threading_package_dependencies = [
    "_pthread_mutex_destroy", "_pthread_cond_broadcast",
    "_pthread_get_stacksize_np", "_pthread_key_create", "_pthread_self",
    "_pthread_equal", "_pthread_mutex_lock", "_pthread_getspecific",
    "_pthread_mutex_unlock", "_pthread_cond_wait", "_pthread_setspecific",
    "_pthread_get_stackaddr_np"
]
common_expected_dependencies = [
    "___bzero", "___divti3", "___error", "___stderrp", "___stdoutp",
    "___truncsfhf2", "___udivti3", "_abort", "_arc4random_buf",
    "_calloc", "_close", "_fflush", "_flockfile", "_fprintf",
    "_fputc", "_fputs", "_free", "_funlockfile", "_fwrite", "_malloc",
    "_malloc_size", "_memchr", "_memcmp", "_memcpy", "_memmove", "_memset",
    "_posix_memalign", "_putc", "_read", "_realloc", "_snprintf", "_strchr",
    "_strcmp", "_strdup", "_strlen", "_strncmp", "_strtod", "_strtof",
    "_strtol", "_strtold", "_vprintf", "_vsnprintf", "_write",
] + cxx_dependencies + math_dependencies
vendor_apple_specific_dependencies = [
    "___stack_chk_fail", "___stack_chk_guard",
    "_getsectiondata", "__dyld_register_func_for_add_image",
]
################################################################################


if args.vendor == "apple":
    vendor_specific_dependencies = vendor_apple_specific_dependencies

    nm = args.nm_path
    lines = subprocess.check_output(
        [nm, "--portability", "--undefined-only", args.library]) \
        .decode("utf-8").strip().splitlines()
    deps = [line.split(" ")[0] for line in lines if " U " in line]
    print("")
else:
    print("vendor {} not handled yet".format(args.vendor))
    sys.exit(1)

deps = [dep for dep in deps if not dep.startswith("_$")]
deps = [dep for dep in deps if not dep.startswith("__Z")]
deps = [dep for dep in deps if not dep.startswith("section$start$")]
deps = [dep for dep in deps if not dep.startswith("section$end$")]
deps = [dep for dep in deps if not dep.startswith("___swift_stdlib")]
deps = [dep for dep in deps if not dep.startswith("__swift_stdlib")]
deps = [dep for dep in deps if not dep.startswith("__swift")]
deps = [dep for dep in deps if not dep.startswith("_swift_")]
deps = [dep for dep in deps if not dep.startswith("__stdlib_")]
deps = [dep for dep in deps if not dep.startswith("_getSuperclassMetadata")]

deps = set(deps)

print("libswiftCore.a dependencies:")
print("\n".join(sorted(deps)))
print("")

# for soundness checking that we are getting a valid symbol list
required_dependencies = ["_malloc", "_free"]

fail = False
for symbol in required_dependencies:
    if symbol not in deps:
        print("Error: Required dependency '{}' missing".format(symbol))
        fail = True

allowlist = set(common_expected_dependencies + vendor_specific_dependencies +
                threading_package_dependencies)
for symbol in deps:
    if symbol not in allowlist:
        print("Error: Unexpected dependency '{}'".format(symbol))
        fail = True

for symbol in allowlist:
    if symbol not in deps:
        print("Warning: Allowed dependency '{}' not present".format(symbol))

print("")
print("All checks done. Result: {}".format("FAIL" if fail else "SUCCESS"))
sys.exit(1 if fail else 0)