|
| 1 | +#!/usr/bin/env python |
| 2 | +# |
| 3 | +# This source file is part of the Swift.org open source project |
| 4 | +# |
| 5 | +# Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| 6 | +# Licensed under Apache License v2.0 with Runtime Library Exception |
| 7 | +# |
| 8 | +# See https://swift.org/LICENSE.txt for license information |
| 9 | +# See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| 10 | + |
| 11 | +import argparse |
| 12 | +import subprocess |
| 13 | +import sys |
| 14 | + |
| 15 | +parser = argparse.ArgumentParser() |
| 16 | +parser.add_argument("--library", help="path to libswiftCore.a to check") |
| 17 | +parser.add_argument("--vendor", help="flavor of the freestanding stdlib") |
| 18 | +parser.add_argument("--nm-path", help="path to llvm-nm binary to use") |
| 19 | +args = parser.parse_args() |
| 20 | + |
| 21 | + |
| 22 | +################################################################################ |
| 23 | +# |
| 24 | +# EXPECTED/ALLOWED DEPENDENCIES |
| 25 | +# |
| 26 | +# Before adding new symbols into these lists please consult with: |
| 27 | +# @kubamracek, @compnerd |
| 28 | +# |
| 29 | +# The 'freestanding' build of the Swift runtime and standard library is |
| 30 | +# intended to depend on as few platform symbols/APIs as possible. |
| 31 | +# |
| 32 | +################################################################################ |
| 33 | +icu_dependencies = [ |
| 34 | + "_u_charAge", "_u_charName", "_u_getIntPropertyValue", "_u_getNumericValue", |
| 35 | + "_u_hasBinaryProperty", "_u_strToLower", "_u_strToTitle", "_u_strToUpper", |
| 36 | + "_ubrk_close", "_ubrk_following", "_ubrk_open", "_ubrk_preceding", |
| 37 | + "_ubrk_setText", "_ubrk_setUText", "_unorm2_getNFCInstance", |
| 38 | + "_unorm2_hasBoundaryBefore", "_unorm2_normalize", |
| 39 | + "_unorm2_spanQuickCheckYes", "_utext_openUChars", "_utext_openUTF8", |
| 40 | +] |
| 41 | +cxx_dependencies = [ |
| 42 | + "___cxa_guard_acquire", "___cxa_guard_release", |
| 43 | +] |
| 44 | +math_dependencies = [ |
| 45 | + "_ceill", "_cos", "_cosf", "_cosl", "_exp", "_exp2", "_exp2f", "_exp2l", |
| 46 | + "_expf", "_expl", "_fma", "_fmaf", "_fmal", "_fmod", "_fmodf", "_fmodl", |
| 47 | + "_log", "_log10", "_log10f", "_log10l", "_log2", "_log2f", "_log2l", |
| 48 | + "_logf", "_logl", "_nearbyintl", "_remainder", "_remainderf", "_remainderl", |
| 49 | + "_rintl", "_roundl", "_sin", "_sinf", "_sinl", "_truncl", |
| 50 | +] |
| 51 | +common_expected_dependencies = [ |
| 52 | + "___bzero", "___divti3", "___error", "___stderrp", "___stdoutp", |
| 53 | + "___truncsfhf2", "___udivti3", "_abort", "_arc4random_buf", "_backtrace", |
| 54 | + "_calloc", "_close", "_environ", "_flockfile", "_floorl", "_fprintf", |
| 55 | + "_fputc", "_fputs", "_free", "_funlockfile", "_fwrite", "_malloc", |
| 56 | + "_malloc_size", "_memchr", "_memcmp", "_memcpy", "_memmove", "_memset", |
| 57 | + "_posix_memalign", "_putc", "_read", "_realloc", "_snprintf", "_strchr", |
| 58 | + "_strcmp", "_strdup", "_strlen", "_strncmp", "_strtod_l", "_strtof_l", |
| 59 | + "_strtol", "_strtold_l", "_vsnprintf", "_write", |
| 60 | +] + icu_dependencies + cxx_dependencies + math_dependencies |
| 61 | +vendor_apple_specific_dependencies = [ |
| 62 | + "__NSGetArgc", "__NSGetArgv", "___stack_chk_fail", "___stack_chk_guard", |
| 63 | + "_asl_log", "_getsectiondata", "__dyld_register_func_for_add_image", |
| 64 | +] |
| 65 | +################################################################################ |
| 66 | + |
| 67 | + |
| 68 | +if args.vendor == "apple": |
| 69 | + vendor_specific_dependencies = vendor_apple_specific_dependencies |
| 70 | + |
| 71 | + nm = args.nm_path |
| 72 | + lines = subprocess.check_output( |
| 73 | + [nm, "--portability", "--undefined-only", args.library]) \ |
| 74 | + .decode("utf-8").strip().splitlines() |
| 75 | + deps = [line.split(" ")[0] for line in lines if " U " in line] |
| 76 | + print("") |
| 77 | +else: |
| 78 | + print("vendor {} not handled yet".format(args.vendor)) |
| 79 | + sys.exit(1) |
| 80 | + |
| 81 | +deps = [dep for dep in deps if not dep.startswith("_$")] |
| 82 | +deps = [dep for dep in deps if not dep.startswith("__Z")] |
| 83 | +deps = [dep for dep in deps if not dep.startswith("section$start$")] |
| 84 | +deps = [dep for dep in deps if not dep.startswith("section$end$")] |
| 85 | +deps = [dep for dep in deps if not dep.startswith("___swift_stdlib")] |
| 86 | +deps = [dep for dep in deps if not dep.startswith("__swift_stdlib")] |
| 87 | +deps = [dep for dep in deps if not dep.startswith("__swift")] |
| 88 | +deps = [dep for dep in deps if not dep.startswith("_swift_")] |
| 89 | +deps = [dep for dep in deps if not dep.startswith("__stdlib_")] |
| 90 | +deps = [dep for dep in deps if not dep.startswith("_getSuperclassMetadata")] |
| 91 | + |
| 92 | +deps = set(deps) |
| 93 | + |
| 94 | +print("libswiftCore.a dependencies:") |
| 95 | +print("\n".join(sorted(deps))) |
| 96 | +print("") |
| 97 | + |
| 98 | +# for sanity checking that we are getting a valid symbol list |
| 99 | +required_dependencies = ["_malloc", "_free"] |
| 100 | + |
| 101 | +fail = False |
| 102 | +for symbol in required_dependencies: |
| 103 | + if symbol not in deps: |
| 104 | + print("Error: Required dependency '{}' missing".format(symbol)) |
| 105 | + fail = True |
| 106 | + |
| 107 | +allowlist = set(common_expected_dependencies + vendor_specific_dependencies) |
| 108 | +for symbol in deps: |
| 109 | + if symbol not in allowlist: |
| 110 | + print("Error: Unexpected dependency '{}'".format(symbol)) |
| 111 | + fail = True |
| 112 | + |
| 113 | +for symbol in allowlist: |
| 114 | + if symbol not in deps: |
| 115 | + print("Warning: Allowed dependency '{}' not present".format(symbol)) |
| 116 | + |
| 117 | +print("") |
| 118 | +print("All checks done. Result: {}".format("FAIL" if fail else "SUCCESS")) |
| 119 | +sys.exit(1 if fail else 0) |
0 commit comments