Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 # 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.
| |
| 6 | |
| 7 # Can just run: | |
| 8 # java -jar third_party/proguard/lib/retrace.jar -regex \ | |
| 9 # "(?:.*?\bat\s+%c\.%m\s*\(%s(?::%l)?\)\s*)|(?:(?:.*?[:\"]\s+)?%c(?::.*)?)" \ | |
| 10 # ~/mapping | |
| 11 # in terminal to achieve same effect as this tool. | |
| 12 | |
| 13 import argparse | |
| 14 import fcntl | |
| 15 import os | |
| 16 import select | |
| 17 import subprocess | |
| 18 import time | |
| 19 | |
| 20 # This regex is taken from | |
| 21 # http://proguard.sourceforge.net/manual/retrace/usage.html. | |
| 22 LINE_PARSE_REGEX = ( | |
|
agrieve
2016/07/08 14:40:13
nit: prefix with _
smaier
2016/07/08 16:00:30
Done.
| |
| 23 r'(?:.*?\bat\s+%c\.%m\s*\(%s(?::%l)?\)\s*)|(?:(?:.*?[:"]\s+)?%c(?::.*)?)') | |
| 24 | |
|
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.
| |
| 25 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.
| |
| 26 poll_interval=1): | |
| 27 try: | |
| 28 # Enable non-blocking reads from the child's stdout. | |
| 29 child_fd = process.stdout.fileno() | |
| 30 fl = fcntl.fcntl(child_fd, fcntl.F_GETFL) | |
| 31 fcntl.fcntl(child_fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) | |
| 32 | |
| 33 end_time = (time.time() + timeout) if timeout else None | |
| 34 while True: | |
| 35 if end_time and time.time() > end_time: | |
| 36 break | |
| 37 read_fds, _, _ = select.select([child_fd], [], [], poll_interval) | |
| 38 if child_fd in read_fds: | |
| 39 data = os.read(child_fd, buffer_size) | |
| 40 if not data: | |
| 41 break | |
| 42 yield data | |
| 43 if process.poll() is not None: | |
| 44 break | |
| 45 finally: | |
| 46 try: | |
| 47 # Make sure the process doesn't stick around if we fail with an | |
| 48 # exception. | |
| 49 process.kill() | |
| 50 except OSError: | |
| 51 pass | |
| 52 process.wait() | |
| 53 | |
| 54 def _IterCmdOutputLines(args): | |
| 55 process = subprocess.Popen( | |
| 56 args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | |
| 57 buffer_output = '' | |
| 58 for data in _IterProcessStdout(process): | |
| 59 buffer_output += data | |
| 60 has_incomplete_line = buffer_output[-1] not in '\r\n' | |
| 61 lines = buffer_output.splitlines() | |
| 62 buffer_output = lines.pop() if has_incomplete_line else '' | |
| 63 for line in lines: | |
| 64 yield line | |
| 65 if buffer_output: | |
| 66 yield buffer_output | |
| 67 | |
| 68 def main(): | |
| 69 parser = argparse.ArgumentParser( | |
| 70 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.
| |
| 71 'that have been mangled by ProGuard. Takes stack traces ' | |
| 72 'from stdin (eg. adb logcat | ' | |
| 73 'java_deobfuscate.py proguard.mapping) and files.')) | |
| 74 parser.add_argument( | |
| 75 'mapping_file', | |
| 76 help='ProGuard mapping file from build which the stacktrace is from.') | |
| 77 parser.add_argument( | |
| 78 '--stacktrace', | |
| 79 help='Stacktrace file to be deobfuscated.') | |
| 80 args = parser.parse_args() | |
| 81 | |
| 82 retrace_path = os.path.abspath(os.path.join( | |
| 83 os.path.abspath(__file__), os.pardir, os.pardir, os.pardir, 'third_party', | |
| 84 'proguard', 'lib', 'retrace.jar')) | |
| 85 | |
| 86 base_args = ['java', '-jar', retrace_path, '-regex', LINE_PARSE_REGEX, | |
| 87 args.mapping_file] | |
| 88 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.
| |
| 89 subprocess.call(base_args + [args.stacktrace]) | |
| 90 else: | |
| 91 for line in _IterCmdOutputLines(base_args): | |
| 92 print line | |
| 93 | |
| 94 if __name__ == '__main__': | |
| 95 main() | |
| OLD | NEW |