Index: build/android/java_deobfuscate.py |
diff --git a/build/android/java_deobfuscate.py b/build/android/java_deobfuscate.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..150b87c902b078d6d3e0157d3b03e3986fa78261 |
--- /dev/null |
+++ b/build/android/java_deobfuscate.py |
@@ -0,0 +1,95 @@ |
+# Copyright 2016 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+# A tool to deobfuscate java stack traces |
agrieve
2016/07/08 14:40:13
nit: change this to pydoc:
"""A tool to deobfusca
smaier
2016/07/08 16:00:31
Done.
|
+ |
+# Can just run: |
+# java -jar third_party/proguard/lib/retrace.jar -regex \ |
+# "(?:.*?\bat\s+%c\.%m\s*\(%s(?::%l)?\)\s*)|(?:(?:.*?[:\"]\s+)?%c(?::.*)?)" \ |
+# ~/mapping |
+# in terminal to achieve same effect as this tool. |
+ |
+import argparse |
+import fcntl |
+import os |
+import select |
+import subprocess |
+import time |
+ |
+# This regex is taken from |
+# http://proguard.sourceforge.net/manual/retrace/usage.html. |
+LINE_PARSE_REGEX = ( |
agrieve
2016/07/08 14:40:13
nit: prefix with _
smaier
2016/07/08 16:00:30
Done.
|
+ r'(?:.*?\bat\s+%c\.%m\s*\(%s(?::%l)?\)\s*)|(?:(?:.*?[:"]\s+)?%c(?::.*)?)') |
+ |
agrieve
2016/07/08 14:40:14
nit: here and below - 2 blank lines between top-le
smaier
2016/07/08 16:00:31
Done.
|
+def _IterProcessStdout(process, timeout=None, buffer_size=4096, |
agrieve
2016/07/08 14:40:14
Probably it'd be nicer to depend on the version in
smaier
2016/07/08 16:00:30
Done.
|
+ poll_interval=1): |
+ try: |
+ # Enable non-blocking reads from the child's stdout. |
+ child_fd = process.stdout.fileno() |
+ fl = fcntl.fcntl(child_fd, fcntl.F_GETFL) |
+ fcntl.fcntl(child_fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) |
+ |
+ end_time = (time.time() + timeout) if timeout else None |
+ while True: |
+ if end_time and time.time() > end_time: |
+ break |
+ read_fds, _, _ = select.select([child_fd], [], [], poll_interval) |
+ if child_fd in read_fds: |
+ data = os.read(child_fd, buffer_size) |
+ if not data: |
+ break |
+ yield data |
+ if process.poll() is not None: |
+ break |
+ finally: |
+ try: |
+ # Make sure the process doesn't stick around if we fail with an |
+ # exception. |
+ process.kill() |
+ except OSError: |
+ pass |
+ process.wait() |
+ |
+def _IterCmdOutputLines(args): |
+ process = subprocess.Popen( |
+ args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
+ buffer_output = '' |
+ for data in _IterProcessStdout(process): |
+ buffer_output += data |
+ has_incomplete_line = buffer_output[-1] not in '\r\n' |
+ lines = buffer_output.splitlines() |
+ buffer_output = lines.pop() if has_incomplete_line else '' |
+ for line in lines: |
+ yield line |
+ if buffer_output: |
+ yield buffer_output |
+ |
+def main(): |
+ parser = argparse.ArgumentParser( |
+ description=('Utility wrapper around ReTrace to deobfuscate stack traces ' |
agrieve
2016/07/08 14:40:13
move this to file's docstring and use: description
smaier
2016/07/08 16:00:30
Done.
|
+ 'that have been mangled by ProGuard. Takes stack traces ' |
+ 'from stdin (eg. adb logcat | ' |
+ 'java_deobfuscate.py proguard.mapping) and files.')) |
+ parser.add_argument( |
+ 'mapping_file', |
+ help='ProGuard mapping file from build which the stacktrace is from.') |
+ parser.add_argument( |
+ '--stacktrace', |
+ help='Stacktrace file to be deobfuscated.') |
+ args = parser.parse_args() |
+ |
+ retrace_path = os.path.abspath(os.path.join( |
+ os.path.abspath(__file__), os.pardir, os.pardir, os.pardir, 'third_party', |
+ 'proguard', 'lib', 'retrace.jar')) |
+ |
+ base_args = ['java', '-jar', retrace_path, '-regex', LINE_PARSE_REGEX, |
+ args.mapping_file] |
+ if args.stacktrace is not None: |
agrieve
2016/07/08 14:40:13
nit: drop the "is not None" part
smaier
2016/07/08 16:00:31
Done.
|
+ subprocess.call(base_args + [args.stacktrace]) |
+ else: |
+ for line in _IterCmdOutputLines(base_args): |
+ print line |
+ |
+if __name__ == '__main__': |
+ main() |