Exemplo n.º 1
0
def run_redex_binary(state):
    if state.args.redex_binary is None:
        try:
            state.args.redex_binary = subprocess.check_output(
                ['which', 'redex-all']).rstrip().decode('ascii')
        except subprocess.CalledProcessError:
            pass
    if state.args.redex_binary is None:
        # __file__ can be /path/fb-redex.pex/redex.pyc
        dir_name = dirname(abspath(__file__))
        while not isdir(dir_name):
            dir_name = dirname(dir_name)
        state.args.redex_binary = join(dir_name, 'redex-all')
    if not isfile(state.args.redex_binary) or not os.access(
            state.args.redex_binary, os.X_OK):
        sys.exit('redex-all is not found or is not executable: ' +
                 state.args.redex_binary)
    log('Running redex binary at ' + state.args.redex_binary)

    args = [state.args.redex_binary] + [
        '--apkdir', state.extracted_apk_dir, '--outdir', state.dex_dir
    ]
    if state.args.config:
        args += ['--config', state.args.config]

    if state.args.verify_none_mode or state.config_dict.get(
            "verify_none_mode"):
        args += ['--verify-none-mode']

    if state.args.is_art_build:
        args += ['--is-art-build']

    if state.args.enable_instrument_pass or state.config_dict.get(
            "enable_instrument_pass"):
        args += ['--enable-instrument-pass']

    if state.args.warn:
        args += ['--warn', state.args.warn]
    args += ['--proguard-config=' + x for x in state.args.proguard_configs]
    if state.args.proguard_map:
        args += ['-Sproguard_map=' + state.args.proguard_map]

    args += ['--jarpath=' + x for x in state.args.jarpaths]
    if state.args.printseeds:
        args += ['--printseeds=' + state.args.printseeds]
    if state.args.used_js_assets:
        args += ['--used-js-assets=' + x for x in state.args.used_js_assets]
    if state.args.arch:
        args += ['--arch=' + state.args.arch]
    args += ['-S' + x for x in state.args.passthru]
    args += ['-J' + x for x in state.args.passthru_json]

    args += state.dexen

    # Stop before a pass and output intermediate dex and IR meta data.
    if state.stop_pass_idx != -1:
        args += [
            '--stop-pass',
            str(state.stop_pass_idx), '--output-ir', state.args.output_ir
        ]

    if state.debugger == 'lldb':
        args = ['lldb', '--'] + args
    elif state.debugger == 'gdb':
        args = ['gdb', '--args'] + args

    start = timer()

    if state.args.debug:
        print('cd %s && %s' % (os.getcwd(), ' '.join(map(quote, args))))
        sys.exit()

    env = logger.setup_trace_for_child(os.environ)
    logger.flush()

    add_extra_environment_args(env)

    # Our CI system occasionally fails because it is trying to write the
    # redex-all binary when this tries to run.  This shouldn't happen, and
    # might be caused by a JVM bug.  Anyways, let's retry and hope it stops.
    for i in range(5):
        try:
            subprocess.check_call(args, env=env)
        except OSError as err:
            if err.errno == errno.ETXTBSY:
                if i < 4:
                    time.sleep(5)
                    continue
            raise err
        except subprocess.CalledProcessError as err:
            script_filenames = write_debugger_commands(args)
            raise RuntimeError(
                ('redex-all crashed with exit code %s! ' % err.returncode) +
                ('You can re-run it '
                 'under gdb by running %(gdb_script_name)s or under lldb '
                 'by running %(lldb_script_name)s') % script_filenames)
        break
    log('Dex processing finished in {:.2f} seconds'.format(timer() - start))
Exemplo n.º 2
0
def run_redex_binary(state, exception_formatter, output_line_handler):
    if state.args.redex_binary is None:
        state.args.redex_binary = shutil.which("redex-all")

    if state.args.redex_binary is None:
        # __file__ can be /path/fb-redex.pex/redex.pyc
        dir_name = dirname(abspath(__file__))
        while not isdir(dir_name):
            dir_name = dirname(dir_name)
        state.args.redex_binary = join(dir_name, "redex-all")
    if not isfile(state.args.redex_binary) or not os.access(
            state.args.redex_binary, os.X_OK):
        sys.exit("redex-all is not found or is not executable: " +
                 state.args.redex_binary)
    logging.debug("Running redex binary at %s", state.args.redex_binary)

    args = [state.args.redex_binary] + [
        "--apkdir",
        state.extracted_apk_dir,
        "--outdir",
        state.dex_dir,
    ]

    if state.args.cmd_prefix is not None:
        args = shlex.split(state.args.cmd_prefix) + args

    if state.args.config:
        args += ["--config", state.args.config]

    if state.args.verify_none_mode or state.config_dict.get(
            "verify_none_mode"):
        args += ["--verify-none-mode"]

    if state.args.is_art_build:
        args += ["--is-art-build"]

    if state.args.redacted:
        args += ["--redacted"]

    if state.args.disable_dex_hasher:
        args += ["--disable-dex-hasher"]

    if state.args.enable_instrument_pass or state.config_dict.get(
            "enable_instrument_pass"):
        args += ["--enable-instrument-pass"]

    if state.args.warn:
        args += ["--warn", state.args.warn]
    args += ["--proguard-config=" + x for x in state.args.proguard_configs]
    if state.args.proguard_map:
        args += ["-Sproguard_map=" + state.args.proguard_map]

    args += ["--jarpath=" + x for x in state.args.jarpaths]
    if state.args.printseeds:
        args += ["--printseeds=" + state.args.printseeds]
    if state.args.used_js_assets:
        args += ["--used-js-assets=" + x for x in state.args.used_js_assets]
    if state.args.arch:
        args += ["--arch=" + state.args.arch]
    args += ["-S" + x for x in state.args.passthru]
    args += ["-J" + x for x in state.args.passthru_json]

    args += state.dexen

    # Stop before a pass and output intermediate dex and IR meta data.
    if state.stop_pass_idx != -1:
        args += [
            "--stop-pass",
            str(state.stop_pass_idx),
            "--output-ir",
            state.args.output_ir,
        ]

    prefix = (dbg_prefix(state.debugger, state.args.debug_source_root)
              if state.debugger is not None else [])
    start = timer()

    if state.args.debug:
        print("cd %s && %s" %
              (os.getcwd(), " ".join(prefix + list(map(quote, args)))))
        sys.exit()

    env = os.environ.copy()
    if state.args.quiet:
        # Remove TRACE if it exists.
        env.pop("TRACE", None)
    else:
        # Check whether TRACE is set. If not, use "TIME:1,PM:1".
        if "TRACE" not in env:
            env["TRACE"] = "TIME:1,PM:1"

    env = logger.setup_trace_for_child(env)
    logger.flush()

    add_extra_environment_args(env)

    def run():
        sigint_handler = SigIntHandler()
        sigint_handler.install()

        try:
            proc, handler = run_and_stream_stderr(prefix + args, env,
                                                  (logger.trace_fp.fileno(), ))
            sigint_handler.set_proc(proc)
            sigint_handler.set_state(RedexState.STARTED)

            returncode, err_out = handler(output_line_handler)

            sigint_handler.set_state(RedexState.POSTPROCESSING)

            if returncode != 0:
                # Check for crash traces.
                maybe_addr2line(err_out)

                abort_error = None
                if returncode == -6:  # SIGABRT
                    abort_error = find_abort_error(err_out)
                if abort_error is not None:
                    abort_error = "\n" + abort_error
                else:
                    abort_error = ""

                default_error_msg = "redex-all crashed with exit code {}!{}".format(
                    returncode, abort_error)
                if IS_WINDOWS:
                    raise RuntimeError(default_error_msg)

                gdb_script_name = write_debugger_command(
                    "gdb", state.args.debug_source_root, args)
                lldb_script_name = write_debugger_command(
                    "lldb", state.args.debug_source_root, args)
                msg = exception_formatter.format_message(
                    err_out, default_error_msg, gdb_script_name,
                    lldb_script_name)
                raise RuntimeError(msg)
            return True
        except OSError as err:
            if err.errno == errno.ETXTBSY:
                return False
            raise err
        finally:
            sigint_handler.set_state(RedexState.FINISHED)
            sigint_handler.uninstall()

    # Our CI system occasionally fails because it is trying to write the
    # redex-all binary when this tries to run.  This shouldn't happen, and
    # might be caused by a JVM bug.  Anyways, let's retry and hope it stops.
    for _ in range(5):
        if run():
            break

    logging.debug("Dex processing finished in {:.2f} seconds".format(timer() -
                                                                     start))
Exemplo n.º 3
0
def run_redex_binary(state):
    if state.args.redex_binary is None:
        state.args.redex_binary = shutil.which("redex-all")

    if state.args.redex_binary is None:
        # __file__ can be /path/fb-redex.pex/redex.pyc
        dir_name = dirname(abspath(__file__))
        while not isdir(dir_name):
            dir_name = dirname(dir_name)
        state.args.redex_binary = join(dir_name, "redex-all")
    if not isfile(state.args.redex_binary) or not os.access(
            state.args.redex_binary, os.X_OK):
        sys.exit("redex-all is not found or is not executable: " +
                 state.args.redex_binary)
    log("Running redex binary at " + state.args.redex_binary)

    args = [state.args.redex_binary] + [
        "--apkdir",
        state.extracted_apk_dir,
        "--outdir",
        state.dex_dir,
    ]
    if state.args.config:
        args += ["--config", state.args.config]

    if state.args.verify_none_mode or state.config_dict.get(
            "verify_none_mode"):
        args += ["--verify-none-mode"]

    if state.args.is_art_build:
        args += ["--is-art-build"]

    if state.args.force_class_data_end_of_file:
        args += ["--force-class-data-end-of-file"]

    if state.args.disable_dex_hasher:
        args += ["--disable-dex-hasher"]

    if state.args.enable_instrument_pass or state.config_dict.get(
            "enable_instrument_pass"):
        args += ["--enable-instrument-pass"]

    if state.args.warn:
        args += ["--warn", state.args.warn]
    args += ["--proguard-config=" + x for x in state.args.proguard_configs]
    if state.args.proguard_map:
        args += ["-Sproguard_map=" + state.args.proguard_map]

    args += ["--jarpath=" + x for x in state.args.jarpaths]
    if state.args.printseeds:
        args += ["--printseeds=" + state.args.printseeds]
    if state.args.used_js_assets:
        args += ["--used-js-assets=" + x for x in state.args.used_js_assets]
    if state.args.arch:
        args += ["--arch=" + state.args.arch]
    args += ["-S" + x for x in state.args.passthru]
    args += ["-J" + x for x in state.args.passthru_json]

    args += state.dexen

    # Stop before a pass and output intermediate dex and IR meta data.
    if state.stop_pass_idx != -1:
        args += [
            "--stop-pass",
            str(state.stop_pass_idx),
            "--output-ir",
            state.args.output_ir,
        ]

    if state.debugger == "lldb":
        args = ["lldb", "--"] + args
    elif state.debugger == "gdb":
        args = ["gdb", "--args"] + args

    start = timer()

    if state.args.debug:
        print("cd %s && %s" % (os.getcwd(), " ".join(map(quote, args))))
        sys.exit()

    env = logger.setup_trace_for_child(os.environ)
    logger.flush()

    add_extra_environment_args(env)

    def run():
        sigint_handler = SigIntHandler()
        sigint_handler.install()

        try:
            proc, handler = run_and_stream_stderr(args, env,
                                                  (logger.trace_fp.fileno(), ))
            sigint_handler.set_proc(proc)
            sigint_handler.set_state(RedexState.STARTED)

            returncode, err_out = handler()

            sigint_handler.set_state(RedexState.POSTPROCESSING)

            if returncode != 0:
                # Check for crash traces.
                maybe_addr2line(err_out)

                script_filenames = write_debugger_commands(args)
                raise RuntimeError(
                    ("redex-all crashed with exit code %s! " % returncode) +
                    ("You can re-run it "
                     "under gdb by running %(gdb_script_name)s or under lldb "
                     "by running %(lldb_script_name)s") % script_filenames)
            return True
        except OSError as err:
            if err.errno == errno.ETXTBSY:
                return False
            raise err
        finally:
            sigint_handler.set_state(RedexState.FINISHED)
            sigint_handler.uninstall()

    # Our CI system occasionally fails because it is trying to write the
    # redex-all binary when this tries to run.  This shouldn't happen, and
    # might be caused by a JVM bug.  Anyways, let's retry and hope it stops.
    for _ in range(5):
        if run():
            break

    log("Dex processing finished in {:.2f} seconds".format(timer() - start))
Exemplo n.º 4
0
def run_pass(
        executable_path,
        script_args,
        config_path,
        config_json,
        apk_dir,
        dex_dir,
        dexfiles,
        debugger,
        ):

    if executable_path is None:
        try:
            executable_path = subprocess.check_output(['which', 'redex-all']
                                                     ).rstrip().decode('ascii')
        except subprocess.CalledProcessError:
            pass
    if executable_path is None:
        # __file__ can be /path/fb-redex.pex/redex.pyc
        dir_name = dirname(abspath(__file__))
        while not isdir(dir_name):
            dir_name = dirname(dir_name)
        executable_path = join(dir_name, 'redex-all')
    if not isfile(executable_path) or not os.access(executable_path, os.X_OK):
        sys.exit('redex-all is not found or is not executable: ' + executable_path)
    log('Running redex binary at ' + executable_path)

    args = [executable_path] + [
        '--apkdir', apk_dir,
        '--outdir', dex_dir]
    if config_path:
        args += ['--config', config_path]

    if script_args.verify_none_mode or config_json.get("verify_none_mode"):
        args += ['--verify-none-mode']

    if script_args.is_art_build:
        args += ['--is-art-build']

    if script_args.warn:
        args += ['--warn', script_args.warn]
    args += ['--proguard-config=' + x for x in script_args.proguard_configs]
    if script_args.proguard_map:
        args += ['-Sproguard_map=' + script_args.proguard_map]

    args += ['--jarpath=' + x for x in script_args.jarpaths]
    if script_args.printseeds:
        args += ['--printseeds=' + script_args.printseeds]
    args += ['-S' + x for x in script_args.passthru]
    args += ['-J' + x for x in script_args.passthru_json]

    args += dexfiles

    if debugger == 'lldb':
        args = ['lldb', '--'] + args
    elif debugger == 'gdb':
        args = ['gdb', '--args'] + args

    start = timer()

    if script_args.debug:
        print(' '.join(map(quote, args)))
        sys.exit()

    env = logger.setup_trace_for_child(os.environ)
    logger.flush()

    add_extra_environment_args(env)

    # Our CI system occasionally fails because it is trying to write the
    # redex-all binary when this tries to run.  This shouldn't happen, and
    # might be caused by a JVM bug.  Anyways, let's retry and hope it stops.
    for i in range(5):
        try:
            subprocess.check_call(args, env=env)
        except OSError as err:
            if err.errno == errno.ETXTBSY:
                if i < 4:
                    time.sleep(5)
                    continue
            raise err
        except subprocess.CalledProcessError as err:
            script_filenames = write_debugger_commands(args)
            raise RuntimeError(
                ('redex-all crashed with exit code %s! ' % err.returncode) +
                ('You can re-run it '
                 'under gdb by running %(gdb_script_name)s or under lldb '
                 'by running %(lldb_script_name)s') % script_filenames)
        break
    log('Dex processing finished in {:.2f} seconds'.format(timer() - start))
Exemplo n.º 5
0
def run_redex_binary(state):
    if state.args.redex_binary is None:
        try:
            state.args.redex_binary = subprocess.check_output(['which', 'redex-all']
                                                              ).rstrip().decode('ascii')
        except subprocess.CalledProcessError:
            pass
    if state.args.redex_binary is None:
        # __file__ can be /path/fb-redex.pex/redex.pyc
        dir_name = dirname(abspath(__file__))
        while not isdir(dir_name):
            dir_name = dirname(dir_name)
        state.args.redex_binary = join(dir_name, 'redex-all')
    if not isfile(state.args.redex_binary) or not os.access(state.args.redex_binary, os.X_OK):
        sys.exit('redex-all is not found or is not executable: ' +
                 state.args.redex_binary)
    log('Running redex binary at ' + state.args.redex_binary)

    args = [state.args.redex_binary] + [
        '--apkdir', state.extracted_apk_dir,
        '--outdir', state.dex_dir]
    if state.args.config:
        args += ['--config', state.args.config]

    if state.args.verify_none_mode or state.config_dict.get("verify_none_mode"):
        args += ['--verify-none-mode']

    if state.args.is_art_build:
        args += ['--is-art-build']

    if state.args.enable_instrument_pass or state.config_dict.get("enable_instrument_pass"):
        args += ['--enable-instrument-pass']

    if state.args.warn:
        args += ['--warn', state.args.warn]
    args += ['--proguard-config=' + x for x in state.args.proguard_configs]
    if state.args.proguard_map:
        args += ['-Sproguard_map=' + state.args.proguard_map]

    args += ['--jarpath=' + x for x in state.args.jarpaths]
    if state.args.printseeds:
        args += ['--printseeds=' + state.args.printseeds]
    if state.args.used_js_assets:
        args += ['--used-js-assets=' + x for x in state.args.used_js_assets]
    args += ['-S' + x for x in state.args.passthru]
    args += ['-J' + x for x in state.args.passthru_json]

    args += state.dexen

    # Stop before a pass and output intermediate dex and IR meta data.
    if state.stop_pass_idx != -1:
        args += ['--stop-pass', str(state.stop_pass_idx),
                 '--output-ir', state.args.output_ir]

    if state.debugger == 'lldb':
        args = ['lldb', '--'] + args
    elif state.debugger == 'gdb':
        args = ['gdb', '--args'] + args

    start = timer()

    if state.args.debug:
        print('cd %s && %s' % (os.getcwd(), ' '.join(map(quote, args))))
        sys.exit()

    env = logger.setup_trace_for_child(os.environ)
    logger.flush()

    add_extra_environment_args(env)

    # Our CI system occasionally fails because it is trying to write the
    # redex-all binary when this tries to run.  This shouldn't happen, and
    # might be caused by a JVM bug.  Anyways, let's retry and hope it stops.
    for i in range(5):
        try:
            subprocess.check_call(args, env=env)
        except OSError as err:
            if err.errno == errno.ETXTBSY:
                if i < 4:
                    time.sleep(5)
                    continue
            raise err
        except subprocess.CalledProcessError as err:
            script_filenames = write_debugger_commands(args)
            raise RuntimeError(
                ('redex-all crashed with exit code %s! ' % err.returncode) +
                ('You can re-run it '
                 'under gdb by running %(gdb_script_name)s or under lldb '
                 'by running %(lldb_script_name)s') % script_filenames)
        break
    log('Dex processing finished in {:.2f} seconds'.format(timer() - start))
Exemplo n.º 6
0
def run_pass(
    executable_path,
    script_args,
    config_path,
    config_json,
    apk_dir,
    dex_dir,
    dexfiles,
    debugger,
):

    if executable_path is None:
        try:
            executable_path = subprocess.check_output(['which',
                                                       'redex-all']).rstrip()
        except subprocess.CalledProcessError:
            pass
    if executable_path is None:
        # __file__ can be /path/fb-redex.pex/redex.pyc
        dir_name = dirname(abspath(__file__))
        while not isdir(dir_name):
            dir_name = dirname(dir_name)
        executable_path = join(dir_name, 'redex-all')
    if not isfile(executable_path) or not os.access(executable_path, os.X_OK):
        sys.exit('redex-all is not found or is not executable')
    log('Running redex binary at ' + executable_path)

    args = [executable_path] + ['--apkdir', apk_dir, '--outdir', dex_dir]
    if config_path:
        args += ['--config', config_path]
    if script_args.warn:
        args += ['--warn', script_args.warn]
    args += ['--proguard-config=' + x for x in script_args.proguard_configs]
    if script_args.keep:
        args += ['--seeds', script_args.keep]
    if script_args.proguard_map:
        args += ['-Sproguard_map=' + script_args.proguard_map]

    args += ['--jarpath=' + x for x in script_args.jarpaths]
    if script_args.printseeds:
        args += ['--printseeds=' + script_args.printseeds]
    args += ['-S' + x for x in script_args.passthru]
    args += ['-J' + x for x in script_args.passthru_json]

    args += dexfiles

    if debugger == 'lldb':
        args = ['lldb', '--'] + args
    elif debugger == 'gdb':
        args = ['gdb', '--args'] + args

    start = timer()

    if script_args.debug:
        print(' '.join(args))
        sys.exit()

    env = logger.setup_trace_for_child(os.environ)
    logger.flush()

    # Our CI system occasionally fails because it is trying to write the
    # redex-all binary when this tries to run.  This shouldn't happen, and
    # might be caused by a JVM bug.  Anyways, let's retry and hope it stops.
    for i in range(5):
        try:
            subprocess.check_call(args, env=env)
        except OSError as err:
            if err.errno == errno.ETXTBSY:
                if i < 4:
                    time.sleep(5)
                    continue
            raise err
        except subprocess.CalledProcessError as err:
            err.cmd = ' '.join(args)
            raise err
        break
    log('Dex processing finished in {:.2f} seconds'.format(timer() - start))
Exemplo n.º 7
0
def run_pass(
        executable_path,
        script_args,
        config_path,
        config_json,
        apk_dir,
        dex_dir,
        dexfiles,
        debugger,
        ):

    if executable_path is None:
        try:
            executable_path = subprocess.check_output(['which', 'redex-all']
                                                     ).rstrip().decode('ascii')
        except subprocess.CalledProcessError:
            pass
    if executable_path is None:
        # __file__ can be /path/fb-redex.pex/redex.pyc
        dir_name = dirname(abspath(__file__))
        while not isdir(dir_name):
            dir_name = dirname(dir_name)
        executable_path = join(dir_name, 'redex-all')
    if not isfile(executable_path) or not os.access(executable_path, os.X_OK):
        sys.exit('redex-all is not found or is not executable: ' + executable_path)
    log('Running redex binary at ' + executable_path)

    args = [executable_path] + [
        '--apkdir', apk_dir,
        '--outdir', dex_dir]
    if config_path:
        args += ['--config', config_path]

    if script_args.verify_none_mode or config_json.get("verify_none_mode"):
        args += ['--verify-none-mode']

    if script_args.is_art_build:
        args += ['--is-art-build']

    if script_args.warn:
        args += ['--warn', script_args.warn]
    args += ['--proguard-config=' + x for x in script_args.proguard_configs]
    if script_args.proguard_map:
        args += ['-Sproguard_map=' + script_args.proguard_map]

    args += ['--jarpath=' + x for x in script_args.jarpaths]
    if script_args.printseeds:
        args += ['--printseeds=' + script_args.printseeds]
    if script_args.rmethods:
        args += ['--rmethods=' + script_args.rmethods]
    if script_args.amethods:
        args += ['--amethods=' + script_args.amethods]
    args += ['-S' + x for x in script_args.passthru]
    args += ['-J' + x for x in script_args.passthru_json]

    args += dexfiles

    if debugger == 'lldb':
        args = ['lldb', '--'] + args
    elif debugger == 'gdb':
        args = ['gdb', '--args'] + args

    start = timer()

    if script_args.debug:
        print(' '.join(args))
        sys.exit()

    env = logger.setup_trace_for_child(os.environ)
    logger.flush()

    add_extra_environment_args(env)

    # Our CI system occasionally fails because it is trying to write the
    # redex-all binary when this tries to run.  This shouldn't happen, and
    # might be caused by a JVM bug.  Anyways, let's retry and hope it stops.
    for i in range(5):
        try:
            subprocess.check_call(args, env=env)
        except OSError as err:
            if err.errno == errno.ETXTBSY:
                if i < 4:
                    time.sleep(5)
                    continue
            raise err
        except subprocess.CalledProcessError as err:
            script_filenames = write_debugger_commands(args)
            raise RuntimeError(
                ('redex-all crashed with exit code %s! ' % err.returncode) +
                ('You can re-run it '
                 'under gdb by running %(gdb_script_name)s or under lldb '
                 'by running %(lldb_script_name)s') % script_filenames)
        break
    log('Dex processing finished in {:.2f} seconds'.format(timer() - start))