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 |