def get_nacl_runner(bitsize, bin_dir=None, use_test_library=True, extra_library_paths=None, extra_envs=None): extra_library_paths = extra_library_paths or [] extra_envs = extra_envs or {} # We use the NACL_IRT_DEV_FILENAME interface for unit tests. args = ['env', 'NACL_DANGEROUS_ENABLE_FILE_ACCESS=1'] arch = 'x86_%d' % bitsize sel_ldr = get_nacl_tool('sel_ldr_%s' % arch) irt_core = get_nacl_irt_core(bitsize) if bin_dir: sel_ldr = os.path.join(bin_dir, sel_ldr) irt_core = os.path.join(bin_dir, irt_core) args.extend([sel_ldr, '-a', '-B', irt_core]) library_path = build_common.get_load_library_path() library_path_for_test = build_common.get_load_library_path_for_test() runnable_ld = os.path.join(library_path, 'runnable-ld.so') if use_test_library: library_path = ':'.join([library_path_for_test, library_path]) args.extend([ '-E', 'LD_LIBRARY_PATH=' + ':'.join([library_path] + extra_library_paths) ]) for key, value in extra_envs.iteritems(): args.extend(['-E', '%s=%s' % (key, value)]) args.append(runnable_ld) return args
def get_nacl_runner(bitsize, bin_dir=None, use_test_library=True, extra_library_paths=None, extra_envs=None): extra_library_paths = extra_library_paths or [] extra_envs = extra_envs or {} # We use the NACL_IRT_DEV_FILENAME interface for unit tests. args = ['env', 'NACL_DANGEROUS_ENABLE_FILE_ACCESS=1'] arch = 'x86_%d' % bitsize sel_ldr = get_nacl_tool('sel_ldr_%s' % arch) irt_core = get_nacl_irt_core(bitsize) if bin_dir: sel_ldr = os.path.join(bin_dir, sel_ldr) irt_core = os.path.join(bin_dir, irt_core) args.extend([sel_ldr, '-a', '-B', irt_core]) library_path = build_common.get_load_library_path() library_path_for_test = build_common.get_load_library_path_for_test() runnable_ld = os.path.join(library_path, 'runnable-ld.so') if use_test_library: library_path = ':'.join([library_path_for_test, library_path]) args.extend(['-E', 'LD_LIBRARY_PATH=' + ':'.join([library_path] + extra_library_paths)]) for key, value in extra_envs.iteritems(): args.extend(['-E', '%s=%s' % (key, value)]) args.append(runnable_ld) return args
def _attach_bare_metal_gdb( remote_address, plugin_pid, ssh_options, nacl_helper_nonsfi_path, gdb_type): """Attaches to the gdbserver, running locally or port-forwarded. If |remote_address| is set, it is used for ssh. """ gdb_port = _get_bare_metal_gdb_port(plugin_pid) # Before launching 'gdb', we wait for that the target port is opened. _wait_by_busy_loop( lambda: _is_remote_port_open(_LOCAL_HOST, gdb_port)) gdb_args = [] if nacl_helper_nonsfi_path: gdb_args.append(nacl_helper_nonsfi_path) gdb_args.extend([ '-ex', 'target remote %s:%d' % (_LOCAL_HOST, gdb_port)]) gdb_args.extend(get_gdb_python_init_args()) library_path = os.path.abspath(build_common.get_load_library_path()) gdb_args.extend(get_gdb_python_script_init_args( 'bare_metal_support', arc_nexe=os.path.join( library_path, os.path.basename(build_common.get_runtime_main_nexe())), library_path=library_path, runnable_ld_path=os.path.join(library_path, 'runnable-ld.so'), lock_file=os.path.join(_BARE_METAL_GDB_LOCK_DIR, str(plugin_pid)), remote_address=remote_address, ssh_options=ssh_options)) gdb_args.extend(['-ex', r'echo To start: c or cont\n']) _launch_plugin_gdb(gdb_args, gdb_type)
def _attach_bare_metal_gdb(remote_address, plugin_pid, ssh_options, nacl_helper_nonsfi_path, gdb_type): """Attaches to the gdbserver, running locally or port-forwarded. If |remote_address| is set, it is used for ssh. """ gdb_port = _get_bare_metal_gdb_port(plugin_pid) # Before launching 'gdb', we wait for that the target port is opened. _wait_by_busy_loop(lambda: _is_remote_port_open(_LOCAL_HOST, gdb_port)) gdb_args = [] if nacl_helper_nonsfi_path: gdb_args.append(nacl_helper_nonsfi_path) gdb_args.extend(['-ex', 'target remote %s:%d' % (_LOCAL_HOST, gdb_port)]) gdb_args.extend(get_gdb_python_init_args()) library_path = os.path.abspath(build_common.get_load_library_path()) gdb_args.extend( get_gdb_python_script_init_args( 'bare_metal_support', arc_nexe=os.path.join( library_path, os.path.basename(build_common.get_runtime_main_nexe())), library_path=library_path, runnable_ld_path=os.path.join(library_path, 'runnable-ld.so'), lock_file=os.path.join(_BARE_METAL_GDB_LOCK_DIR, str(plugin_pid)), remote_address=remote_address, ssh_options=ssh_options)) gdb_args.extend(['-ex', r'echo To start: c or cont\n']) _launch_plugin_gdb(gdb_args, gdb_type)
def _get_gdb_command_to_inject_bare_metal_gdb_py(main_binary): return ( gdb_util.get_gdb_python_init_args() + gdb_util.get_gdb_python_script_init_args( 'bare_metal_support_for_unittest', nonsfi_loader=toolchain.get_nonsfi_loader(), test_binary=main_binary, library_path=build_common.get_load_library_path(), runnable_ld_path=build_common.get_bionic_runnable_ld_so()))
def _extract_symbols(): # Extract symbols in parallel. with concurrent.CheckedExecutor(concurrent.ThreadPoolExecutor( max_workers=multiprocessing.cpu_count(), daemon=True)) as executor: for root, _, filenames in os.walk(build_common.get_load_library_path()): for filename in filenames: if os.path.splitext(filename)[1] in ['.so', '.nexe']: executor.submit(_extract_symbols_from_one_binary, os.path.join(root, filename))
def generate_binaries_depending_ninjas(_): if (not OPTIONS.is_bare_metal_i686() or not OPTIONS.is_optimized_build() or # None of the targets analyzed are currently built in the open source # repository. open_source.is_open_source_repo() or # Run the checker only when --disable-debug-code is specified. Locations # of static initializers differ depending on the debug-code option. OPTIONS.is_debug_code_enabled() or # The checker only works with debug symbols. not OPTIONS.is_debug_info_enabled()): # The static analysis tool's output varies between debug and non-debug # builds, so we pick non-debug as the default. return n = ninja_generator.NinjaGenerator('analyze_static_initializers') script = staging.as_staging( 'android/external/chromium_org/tools/linux/dump-static-initializers.py' ) n.rule( 'analyze_static_initializers', command=('python src/build/run_python %s -d $in | head --lines=-1 | ' 'egrep -ve \'^# .*\.cpp \' |' 'sed -e \'s/ T\.[0-9]*/ T.XXXXX/\' |' 'diff -u $expect - && touch $out' % script), description='analyze_static_initializers $in') libraries = build_common.CHECKED_LIBRARIES libraries_fullpath = [ os.path.join(build_common.get_load_library_path(), lib) for lib in libraries ] for library in zip(libraries, libraries_fullpath): # You can manually update the text files by running # src/build/update_static_initializer_expectations.py. expect = 'src/build/dump-static-initializers-%s-expected.txt' % library[ 0] result_path = os.path.join( build_common.get_build_dir(), 'dump_static_initializers', 'dump_static_initializers.%s.result' % library[0]) n.build( result_path, 'analyze_static_initializers', library[1], variables={ 'out': result_path, 'expect': expect }, # Add |libraries_fullpath| to implicit= not to run the analyzer # script until all libraries in |libraries_fullpath| become ready. # This makes it easy to use # update_static_initializer_expectations.py especially when you # remove global variables from two or more libraries at the same # time. implicit=[script, expect] + libraries_fullpath)
def main(): signal_util.setup() OPTIONS.parse_configure_file() parsed_args = launch_chrome_options.parse_args(sys.argv) logging_util.setup( level=logging.DEBUG if parsed_args.verbose else logging.INFO) _prepare_chrome_user_data_dir(parsed_args) global _CHROME_PID_PATH _CHROME_PID_PATH = os.path.join(_USER_DATA_DIR, 'chrome.pid') # If there is an X server at :0.0 and GPU is enabled, set it as the # current display. if parsed_args.display: os.environ['DISPLAY'] = parsed_args.display os.chdir(_ROOT_DIR) if not parsed_args.remote: _kill_running_chrome() if parsed_args.run_ninja: build_common.run_ninja() ld_library_path = os.environ.get('LD_LIBRARY_PATH') lib_paths = ld_library_path.split(':') if ld_library_path else [] lib_paths.append(build_common.get_load_library_path()) # Add the directory of the chrome binary so that .so files in the directory # can be loaded. This is needed for loading libudev.so.0. # TODO(crbug.com/375609): Remove the hack once it becomes no longer needed. lib_paths.append(os.path.dirname(_get_chrome_path(parsed_args))) os.environ['LD_LIBRARY_PATH'] = ':'.join(lib_paths) launch_chrome_util.set_environment_for_chrome() if not platform_util.is_running_on_remote_host(): _check_apk_existence(parsed_args) if not platform_util.is_running_on_remote_host(): prep_launch_chrome.prepare_crx(parsed_args) prep_launch_chrome.remove_crx_at_exit_if_needed(parsed_args) if parsed_args.remote: remote_executor.launch_remote_chrome(parsed_args, sys.argv[1:]) else: platform_util.assert_machine(OPTIONS.target()) _check_crx_existence(parsed_args) _run_chrome_iterations(parsed_args) return 0
def init_binary_map(self): if self._binary_map: return self._binary_map = {} for dirpath, dirnames, filenames in (os.walk( build_common.get_load_library_path())): for filename in filenames: if re.match(r'arc_[^/]*\.nexe$', filename): name = '/lib/main.nexe' print 'Used %s as main.nexe' % filename else: name = os.path.basename(filename) if name in self._binary_map: raise Exception('Duplicated binary: ' + name) self._binary_map[name] = os.path.join(dirpath, filename)
def init_binary_map(self): if self._binary_map: return self._binary_map = {} for dirpath, dirnames, filenames in ( os.walk(build_common.get_load_library_path())): for filename in filenames: if re.match(r'arc_[^/]*\.nexe$', filename): name = '/lib/main.nexe' print 'Used %s as main.nexe' % filename else: name = os.path.basename(filename) if name in self._binary_map: raise Exception('Duplicated binary: ' + name) self._binary_map[name] = os.path.join(dirpath, filename)
def _get_runner_env_vars(use_test_library=True, extra_library_paths=None, extra_envs=None): extra_library_paths = extra_library_paths or [] extra_envs = extra_envs or {} load_library_paths = [] if use_test_library: load_library_paths.append(build_common.get_load_library_path_for_test()) load_library_paths.append(build_common.get_load_library_path()) envs = { 'LD_LIBRARY_PATH': ':'.join(load_library_paths + extra_library_paths) } if extra_envs: conflict_keys = envs.viewkeys() & extra_envs.viewkeys() assert not conflict_keys, ('The following keys are duplicated: %s' % sorted(conflict_keys)) envs.update(extra_envs) return envs
def _run_gdb_for_nacl(args, test_args): runnable_ld = args[-1] assert 'runnable-ld.so' in runnable_ld # Insert -g flag before -a to let sel_ldr wait for GDB. a_index = args.index('-a') assert 'sel_ldr' in args[a_index - 1] args.insert(a_index, '-g') args.extend(test_args) # The child process call setsid(2) to create a new session so that # sel_ldr will not die by Ctrl-C either. Note that ignoring SIGINT # does not work for sel_ldr, because sel_ldr will override the # setting. sel_ldr_proc = subprocess.Popen(args, stderr=subprocess.STDOUT, preexec_fn=os.setsid) gdb = toolchain.get_tool(build_options.OPTIONS.target(), 'gdb') irt = toolchain.get_nacl_irt_core(build_options.OPTIONS.get_target_bitsize()) # The Bionic loader only provides the base name of each loaded binary in L # for 32-bit platforms due to a compatibility issue. # ARC keeps the behavior and provides full path information for debugging # explicitly. See SEARCH_NAME() in mods/android/bionic/linker/linker.cpp. # DSOs are covered by build_common.get_load_library_path(), but full path # information for test main binary should be specified separately. # # Note GDB uses NaCl manifest for arc.nexe so we do not need the library # search paths for launch_chrome. solib_paths = [build_common.get_load_library_path_for_test(), build_common.get_load_library_path(), os.path.dirname(test_args[0])] args = [ gdb, '-ex', 'target remote :4014', '-ex', 'nacl-irt %s' % irt, # The Bionic does not pass a fullpath of a shared object to the # debugger. Fixing this issue by modifying the Bionic loader # will need a bunch of ARC MOD. We work-around the issue by # passing the path of shared objects here. '-ex', 'set solib-search-path %s' % ':'.join(solib_paths), '-ex', 'echo \n*** Type \'continue\' or \'c\' to start debugging ***\n\n', runnable_ld] subprocess.call(args) sel_ldr_proc.kill()
def generate_binaries_depending_ninjas(_): if (not OPTIONS.is_bare_metal_i686() or not OPTIONS.is_optimized_build() or # None of the targets analyzed are currently built in the open source # repository. open_source.is_open_source_repo() or # Run the checker only when --disable-debug-code is specified. Locations # of static initializers differ depending on the debug-code option. OPTIONS.is_debug_code_enabled() or # The checker only works with debug symbols. not OPTIONS.is_debug_info_enabled()): # The static analysis tool's output varies between debug and non-debug # builds, so we pick non-debug as the default. return n = ninja_generator.NinjaGenerator('analyze_static_initializers') script = staging.as_staging( 'android/external/chromium_org/tools/linux/dump-static-initializers.py') n.rule('analyze_static_initializers', command=('python src/build/run_python %s -d $in | head --lines=-1 | ' 'egrep -ve \'^# .*\.cpp \' |' 'sed -e \'s/ T\.[0-9]*/ T.XXXXX/\' |' 'diff -u $expect - && touch $out' % script), description='analyze_static_initializers $in') libraries = build_common.CHECKED_LIBRARIES libraries_fullpath = [ os.path.join(build_common.get_load_library_path(), lib) for lib in libraries] for library in zip(libraries, libraries_fullpath): # You can manually update the text files by running # src/build/update_static_initializer_expectations.py. expect = 'src/build/dump-static-initializers-%s-expected.txt' % library[0] result_path = os.path.join(build_common.get_build_dir(), 'dump_static_initializers', 'dump_static_initializers.%s.result' % library[0]) n.build(result_path, 'analyze_static_initializers', library[1], variables={'out': result_path, 'expect': expect}, # Add |libraries_fullpath| to implicit= not to run the analyzer # script until all libraries in |libraries_fullpath| become ready. # This makes it easy to use # update_static_initializer_expectations.py especially when you # remove global variables from two or more libraries at the same # time. implicit=[script, expect] + libraries_fullpath)
def get_bare_metal_runner(nacl_arch=None, use_qemu_arm=False, bin_dir=None, use_test_library=True, extra_library_paths=None, extra_envs=None, with_env_cmd=True): args = [] if with_env_cmd: args.append('env') envs = _get_runner_env_vars(use_test_library, extra_library_paths, extra_envs) args.extend('%s=%s' % item for item in envs.iteritems()) if use_qemu_arm: args.extend(get_qemu_arm_args()) loader = get_nonsfi_loader(nacl_arch) if bin_dir: loader = os.path.join(bin_dir, loader) args.append(loader) args.append(os.path.join(build_common.get_load_library_path(), 'runnable-ld.so')) return args
def _get_runner_env_vars(use_test_library=True, extra_library_paths=None, extra_envs=None): extra_library_paths = extra_library_paths or [] extra_envs = extra_envs or {} load_library_paths = [] if use_test_library: load_library_paths.append( build_common.get_load_library_path_for_test()) load_library_paths.append(build_common.get_load_library_path()) envs = { 'LD_LIBRARY_PATH': ':'.join(load_library_paths + extra_library_paths) } if extra_envs: conflict_keys = envs.viewkeys() & extra_envs.viewkeys() assert not conflict_keys, ('The following keys are duplicated: %s' % sorted(conflict_keys)) envs.update(extra_envs) return envs
def _generate_libposix_translation_for_test(): n = ninja_generator.SharedObjectNinjaGenerator( 'libposix_translation_for_test', dt_soname='libposix_translation.so', is_system_library=True, is_for_test=True) # libposix_translation_for_test is built using generated code in the out/ # directory. The logic we have to scan for NOTICES does not find one for this # generated code, and complains later. The libposix_translation.so code # normally inherits the project NOTICE from src/NOTICE, so we just explicitly # point to it here as the notice to use for this special version of the # library. n.add_notice_sources([staging.as_staging('src/NOTICE')]) gen_rule_name = 'gen_wrap_syscall_aliases_s' gen_script_path = os.path.join('src/common', gen_rule_name + '.py') n.rule(gen_rule_name, command='%s > $out.tmp && mv $out.tmp $out' % gen_script_path, description=gen_rule_name + ' $in') gen_out_path = os.path.join(build_common.get_build_dir(), 'posix_translation_gen_sources', 'wrap_syscall_aliases.S') gen_implicit_deps = python_deps.find_deps(gen_script_path) n.build(gen_out_path, gen_rule_name, implicit=gen_implicit_deps) # Following deps order is important. art_libc_supplement_for_test.so should # be placed before libc.so. if not open_source.is_open_source_repo(): # This is for ART unit tests which have not been opensourced. To not let # posix_translation depend on ART on arc_open, use is_open_source_repo(). n.add_library_deps('art_libc_supplement_for_test.so') n.add_library_deps('libc.so', 'libdl.so') n.build_default([gen_out_path], base_path=None).link() # /test/libposix_translation.so should be a symbolic link to # ../lib/libposix_translation_for_test.so. n = ninja_generator.NinjaGenerator('test_libposix_translation') orig_so = os.path.join( build_common.get_load_library_path(), 'libposix_translation_for_test.so') link_so = os.path.join( build_common.get_load_library_path_for_test(), 'libposix_translation.so') command = 'ln -sf %s %s' % ( os.path.join('../../lib/', os.path.basename(orig_so)), link_so) n.build(link_so, 'run_shell_command', implicit=orig_so, variables={'command': command})
def get_bare_metal_runner(nacl_arch=None, use_qemu_arm=False, bin_dir=None, use_test_library=True, extra_library_paths=None, extra_envs=None, with_env_cmd=True): args = [] if with_env_cmd: args.append('env') envs = _get_runner_env_vars(use_test_library, extra_library_paths, extra_envs) args.extend('%s=%s' % item for item in envs.iteritems()) if use_qemu_arm: args.extend(get_qemu_arm_args()) loader = get_nonsfi_loader(nacl_arch) if bin_dir: loader = os.path.join(bin_dir, loader) args.append(loader) args.append( os.path.join(build_common.get_load_library_path(), 'runnable-ld.so')) return args
def _get_native_runner(target): if target == 'host' or target == 'java': return '' return 'env LD_LIBRARY_PATH=' + build_common.get_load_library_path(target)