apk_operations.py: Deobfuscate java stack traces in logcat
Applicable only when building release. Disable via --no-deobfuscate Bug: 620323, 758670 Change-Id: Ib1289e6eae6bb326a1879c791e673cdeba331eab Reviewed-on: https://chromium-review.googlesource.com/656720 Reviewed-by: John Budorick <jbudorick@chromium.org> Reviewed-by: Peter Wen <wnwen@chromium.org> Commit-Queue: Andrew Grieve <agrieve@chromium.org> Cr-Original-Commit-Position: refs/heads/master@{#501645} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 52668623db4ab636e6631b7a3598ad48f3bb292a
This commit is contained in:
Родитель
465f7fab27
Коммит
749b1d8cdd
|
@ -12,7 +12,6 @@ import posixpath
|
|||
import random
|
||||
import re
|
||||
import shlex
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import devil_chromium
|
||||
|
@ -32,6 +31,7 @@ with devil_env.SysPath(os.path.join(os.path.dirname(__file__), '..', '..',
|
|||
|
||||
from incremental_install import installer
|
||||
from pylib import constants
|
||||
from pylib.symbols import deobfuscator
|
||||
|
||||
|
||||
def _Colorize(color, text):
|
||||
|
@ -354,7 +354,15 @@ def _RunDiskUsage(devices, package_name, verbose):
|
|||
print 'Total: %skb (%.1fmb)' % (total, total / 1024.0)
|
||||
|
||||
|
||||
def _RunLogcat(device, package_name, verbose):
|
||||
def _RunLogcat(device, package_name, verbose, mapping_path):
|
||||
if mapping_path:
|
||||
try:
|
||||
deobfuscate = deobfuscator.Deobfuscator(mapping_path)
|
||||
except OSError:
|
||||
sys.stderr.write('Error executing "bin/java_deobfuscate". '
|
||||
'Did you forget to build it?\n')
|
||||
sys.exit(1)
|
||||
|
||||
def get_my_pids():
|
||||
my_pids = []
|
||||
for pids in device.GetPids(package_name).values():
|
||||
|
@ -363,46 +371,52 @@ def _RunLogcat(device, package_name, verbose):
|
|||
|
||||
def process_line(line, fast=False):
|
||||
if verbose:
|
||||
if not fast:
|
||||
sys.stdout.write(line)
|
||||
if fast:
|
||||
return
|
||||
else:
|
||||
if line.startswith('------'):
|
||||
if not line or line.startswith('------'):
|
||||
return
|
||||
tokens = line.split(None, 4)
|
||||
pid = int(tokens[2])
|
||||
priority = tokens[4]
|
||||
if pid in my_pids or (not fast and priority == 'F'):
|
||||
sys.stdout.write(line)
|
||||
pass # write
|
||||
elif pid in not_my_pids:
|
||||
return
|
||||
elif fast:
|
||||
# Skip checking whether our package spawned new processes.
|
||||
not_my_pids.add(pid)
|
||||
return
|
||||
else:
|
||||
# Check and add the pid if it is a new one from our package.
|
||||
my_pids.update(get_my_pids())
|
||||
if pid in my_pids:
|
||||
sys.stdout.write(line)
|
||||
else:
|
||||
if pid not in my_pids:
|
||||
not_my_pids.add(pid)
|
||||
return
|
||||
if mapping_path:
|
||||
line = '\n'.join(deobfuscate.TransformLines([line.rstrip()])) + '\n'
|
||||
sys.stdout.write(line)
|
||||
|
||||
adb_path = adb_wrapper.AdbWrapper.GetAdbPath()
|
||||
cmd = [adb_path, '-s', device.serial, 'logcat', '-v', 'threadtime']
|
||||
process = subprocess.Popen(cmd, stdout=subprocess.PIPE, bufsize=1)
|
||||
my_pids = set(get_my_pids())
|
||||
not_my_pids = set()
|
||||
|
||||
nonce = 'apk_wrappers.py nonce={}'.format(random.random())
|
||||
device.RunShellCommand(['log', nonce])
|
||||
fast = True
|
||||
try:
|
||||
while True:
|
||||
line = process.stdout.readline()
|
||||
process_line(line, fast)
|
||||
my_pids = set(get_my_pids())
|
||||
not_my_pids = set()
|
||||
|
||||
nonce = 'apk_wrappers.py nonce={}'.format(random.random())
|
||||
device.RunShellCommand(['log', nonce])
|
||||
fast = True
|
||||
for line in device.adb.Logcat(logcat_format='threadtime'):
|
||||
try:
|
||||
process_line(line, fast)
|
||||
except:
|
||||
sys.stderr.write('Failed to process line: ' + line)
|
||||
raise
|
||||
if fast and nonce in line:
|
||||
fast = False
|
||||
except KeyboardInterrupt:
|
||||
process.terminate()
|
||||
pass # Don't show stack trace upon Ctrl-C
|
||||
finally:
|
||||
if mapping_path:
|
||||
deobfuscate.Close()
|
||||
|
||||
|
||||
def _RunPs(devices, package_name):
|
||||
|
@ -788,8 +802,20 @@ class _LogcatCommand(_Command):
|
|||
calls_exec = True
|
||||
|
||||
def Run(self):
|
||||
mapping = self.args.proguard_mapping_path
|
||||
if self.args.no_deobfuscate:
|
||||
mapping = None
|
||||
_RunLogcat(self.devices[0], self.args.package_name,
|
||||
bool(self.args.verbose_count))
|
||||
bool(self.args.verbose_count), mapping)
|
||||
|
||||
def _RegisterExtraArgs(self, group):
|
||||
if self._from_wrapper_script:
|
||||
group.add_argument('--no-deobfuscate', action='store_true',
|
||||
help='Disables ProGuard deobfuscation of logcat.')
|
||||
else:
|
||||
group.set_defaults(no_deobfuscate=False)
|
||||
group.add_argument('--proguard-mapping-path',
|
||||
help='Path to ProGuard map (enables deobfuscation)')
|
||||
|
||||
|
||||
class _PsCommand(_Command):
|
||||
|
@ -913,7 +939,7 @@ def _RunInternal(parser, output_directory=None):
|
|||
# TODO(agrieve): Remove =None from target_cpu on or after October 2017.
|
||||
# It exists only so that stale wrapper scripts continue to work.
|
||||
def Run(output_directory, apk_path, incremental_json, command_line_flags_file,
|
||||
target_cpu=None):
|
||||
target_cpu, proguard_mapping_path):
|
||||
"""Entry point for generated wrapper scripts."""
|
||||
constants.SetOutputDirectory(output_directory)
|
||||
devil_chromium.Initialize(output_directory=output_directory)
|
||||
|
@ -923,7 +949,8 @@ def Run(output_directory, apk_path, incremental_json, command_line_flags_file,
|
|||
command_line_flags_file=command_line_flags_file,
|
||||
target_cpu=target_cpu,
|
||||
apk_path=exists_or_none(apk_path),
|
||||
incremental_json=exists_or_none(incremental_json))
|
||||
incremental_json=exists_or_none(incremental_json),
|
||||
proguard_mapping_path=proguard_mapping_path)
|
||||
_RunInternal(parser, output_directory=output_directory)
|
||||
|
||||
|
||||
|
@ -933,4 +960,4 @@ def main():
|
|||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
main()
|
||||
|
|
|
@ -26,11 +26,13 @@ def main():
|
|||
import apk_operations
|
||||
output_dir = resolve(${OUTPUT_DIR})
|
||||
try:
|
||||
apk_operations.Run(output_dir,
|
||||
resolve(${APK_PATH}),
|
||||
resolve(${INC_JSON_PATH}),
|
||||
${FLAGS_FILE},
|
||||
target_cpu=${TARGET_CPU})
|
||||
apk_operations.Run(
|
||||
output_dir,
|
||||
resolve(${APK_PATH}),
|
||||
resolve(${INC_JSON_PATH}),
|
||||
${FLAGS_FILE},
|
||||
${TARGET_CPU},
|
||||
resolve(${MAPPING_PATH}))
|
||||
except TypeError:
|
||||
rel_output_dir = os.path.relpath(output_dir)
|
||||
rel_script_path = os.path.relpath(sys.argv[0], output_dir)
|
||||
|
@ -52,6 +54,7 @@ def main(args):
|
|||
parser.add_argument('--incremental-install-json-path')
|
||||
parser.add_argument('--command-line-flags-file')
|
||||
parser.add_argument('--target-cpu')
|
||||
parser.add_argument('--proguard-mapping-path')
|
||||
args = parser.parse_args(args)
|
||||
|
||||
def relativize(path):
|
||||
|
@ -68,6 +71,7 @@ def main(args):
|
|||
'OUTPUT_DIR': repr(relativize('.')),
|
||||
'APK_PATH': repr(relativize(args.apk_path)),
|
||||
'INC_JSON_PATH': repr(relativize(args.incremental_install_json_path)),
|
||||
'MAPPING_PATH': repr(relativize(args.proguard_mapping_path)),
|
||||
'FLAGS_FILE': repr(args.command_line_flags_file),
|
||||
'TARGET_CPU': repr(args.target_cpu),
|
||||
}
|
||||
|
|
|
@ -21,13 +21,15 @@ class Deobfuscator(object):
|
|||
script_path = os.path.join(
|
||||
constants.GetOutDirectory(), 'bin', 'java_deobfuscate')
|
||||
cmd = [script_path, mapping_path]
|
||||
# Allow only one thread to call TransformLines() at a time.
|
||||
self._lock = threading.Lock()
|
||||
self._closed_called = False
|
||||
# Assign to None so that attribute exists if Popen() throws.
|
||||
self._proc = None
|
||||
# Start process eagerly to hide start-up latency.
|
||||
self._proc = subprocess.Popen(
|
||||
cmd, bufsize=1, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
||||
close_fds=True)
|
||||
# Allow only one thread to call TransformLines() at a time.
|
||||
self._lock = threading.Lock()
|
||||
self._closed_called = False
|
||||
|
||||
def IsClosed(self):
|
||||
return self._closed_called or self._proc.returncode is not None
|
||||
|
@ -113,7 +115,8 @@ class Deobfuscator(object):
|
|||
self._proc.wait()
|
||||
|
||||
def __del__(self):
|
||||
if not self._closed_called:
|
||||
# self._proc is None when Popen() fails.
|
||||
if not self._closed_called and self._proc:
|
||||
logging.error('Forgot to Close() deobfuscator')
|
||||
|
||||
|
||||
|
|
|
@ -2492,6 +2492,12 @@ if (enable_java_templates) {
|
|||
outputs = [
|
||||
_generated_script,
|
||||
]
|
||||
if (_proguard_enabled) {
|
||||
# Required by logcat command.
|
||||
data_deps = [
|
||||
"//build/android/stacktrace:java_deobfuscate",
|
||||
]
|
||||
}
|
||||
args = [
|
||||
"--script-output-path",
|
||||
rebase_path(_generated_script, root_build_dir),
|
||||
|
@ -2511,6 +2517,12 @@ if (enable_java_templates) {
|
|||
rebase_path(_incremental_install_json_path, root_build_dir),
|
||||
]
|
||||
}
|
||||
if (_proguard_enabled) {
|
||||
args += [
|
||||
"--proguard-mapping-path",
|
||||
rebase_path("$_final_apk_path.mapping", root_build_dir),
|
||||
]
|
||||
}
|
||||
}
|
||||
_apk_operations += [ ":$_apk_operations_target_name" ]
|
||||
_incremental_apk_operations += [ ":$_apk_operations_target_name" ]
|
||||
|
@ -2686,7 +2698,6 @@ if (enable_java_templates) {
|
|||
proguard_configs = []
|
||||
}
|
||||
proguard_configs += [ "//testing/android/proguard_for_test.flags" ]
|
||||
data_deps += [ "//build/android/stacktrace:java_deobfuscate" ]
|
||||
if (defined(final_apk_path)) {
|
||||
_final_apk_path = final_apk_path
|
||||
} else {
|
||||
|
@ -2828,11 +2839,11 @@ if (enable_java_templates) {
|
|||
}
|
||||
shared_libraries = [ invoker.shared_library ]
|
||||
deps += [
|
||||
":${target_name}__runtime_deps",
|
||||
":${target_name}__secondary_abi_runtime_deps",
|
||||
"//base:base_java",
|
||||
"//testing/android/appurify_support:appurify_support_java",
|
||||
"//testing/android/reporter:reporter_java",
|
||||
":${target_name}__runtime_deps",
|
||||
":${target_name}__secondary_abi_runtime_deps",
|
||||
]
|
||||
data_deps += [
|
||||
"//build/android/pylib/device/commands",
|
||||
|
|
Загрузка…
Ссылка в новой задаче