1#!/usr/bin/env python3 2# Copyright 2018 The Chromium Authors 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5"""Generate linker version scripts for Chrome on Android shared libraries.""" 6 7import argparse 8import os 9 10from util import build_utils 11import action_helpers # build_utils adds //build to sys.path. 12 13_SCRIPT_HEADER = """\ 14# AUTO-GENERATED FILE. DO NOT MODIFY. 15# 16# See: %s 17 18{ 19 global: 20""" % os.path.relpath(__file__, build_utils.DIR_SOURCE_ROOT) 21 22_SCRIPT_FOOTER = """\ 23 local: 24 *; 25}; 26""" 27 28 29def main(): 30 parser = argparse.ArgumentParser() 31 parser.add_argument( 32 '--output', 33 required=True, 34 help='Path to output linker version script file.') 35 parser.add_argument( 36 '--jni-multiplexing', 37 action='store_true', 38 help='Export only the JNI methods generated by multiplexing') 39 parser.add_argument('--export-fortesting-java-symbols', 40 action='store_true', 41 help='Export Java_*_ForTesting JNI methods') 42 parser.add_argument( 43 '--export-symbol-allowlist-file', 44 action='append', 45 default=[], 46 dest='allowlists', 47 help='Path to an input file containing an allowlist of extra symbols to ' 48 'export, one symbol per line. Multiple files may be specified.') 49 parser.add_argument( 50 '--export-feature-registrations', 51 action='store_true', 52 help='Export JNI_OnLoad_* methods') 53 options = parser.parse_args() 54 55 # JNI_OnLoad is always exported. 56 # CrashpadHandlerMain() is the entry point to the Crashpad handler, required 57 # for libcrashpad_handler_trampoline.so. 58 symbol_list = ['CrashpadHandlerMain', 'JNI_OnLoad'] 59 60 if options.jni_multiplexing: 61 symbol_list.append('Java_J_*N__*') 62 elif options.export_fortesting_java_symbols: 63 symbol_list.append('Java_*') 64 else: 65 # The linker uses unix shell globbing patterns, not regex. So, we have to 66 # include everything that doesn't end in "ForTest(ing)" with this set of 67 # globs. 68 symbol_list.append('Java_*[!F]orTesting') 69 symbol_list.append('Java_*[!o]rTesting') 70 symbol_list.append('Java_*[!r]Testing') 71 symbol_list.append('Java_*[!T]esting') 72 symbol_list.append('Java_*[!e]sting') 73 symbol_list.append('Java_*[!s]ting') 74 symbol_list.append('Java_*[!t]ing') 75 symbol_list.append('Java_*[!i]ng') 76 symbol_list.append('Java_*[!n]g') 77 symbol_list.append('Java_*[!F]orTest') 78 symbol_list.append('Java_*[!o]rTest') 79 symbol_list.append('Java_*[!r]Test') 80 symbol_list.append('Java_*[!T]est') 81 symbol_list.append('Java_*[!e]st') 82 symbol_list.append('Java_*[!s]t') 83 symbol_list.append('Java_*[!gt]') 84 85 if options.export_feature_registrations: 86 symbol_list.append('JNI_OnLoad_*') 87 88 for allowlist in options.allowlists: 89 with open(allowlist, 'rt') as f: 90 for line in f: 91 line = line.strip() 92 if not line or line[0] == '#': 93 continue 94 symbol_list.append(line) 95 96 script_content = [_SCRIPT_HEADER] 97 for symbol in symbol_list: 98 script_content.append(' %s;\n' % symbol) 99 script_content.append(_SCRIPT_FOOTER) 100 101 script = ''.join(script_content) 102 103 with action_helpers.atomic_output(options.output, mode='w') as f: 104 f.write(script) 105 106 107if __name__ == '__main__': 108 main() 109