| #!/usr/bin/env python3 | |
| # Copyright 2019 The Fuchsia Authors. All rights reserved. | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| """ Pipe `fx syslog` through this tool for simpler stack traces. | |
| E.g. `fx syslog | scripts/simplify_stacktraces`. | |
| """ | |
| import sys | |
| import re | |
| TEMPLATE_TAG = "###TEMPLATE###" | |
| class TerminalEscapeCodes: | |
| GREEN = '\033[92m' | |
| ENDC = '\033[0m' | |
| UNDERLINE = '\033[4m' | |
| def simplify_cpp_file_path(path): | |
| return re.sub(r"^../../out/[^/]+/../../", "", path) | |
| def simplify_cpp_function_signature(function): | |
| # To find "core part" to underline, strip out all param lists and templated | |
| # types. | |
| core_part = function | |
| while True: | |
| prev = core_part | |
| core_part = re.sub(r"<[^<>]*>", "", core_part) | |
| core_part = re.sub(r"\([^\(\)]*\)", "", core_part) | |
| if prev == core_part: | |
| break | |
| core_part = re.sub(r"::\$[^:]+::operator", "", core_part) | |
| core_part = re.sub(r"::'lambda'::operator", "", core_part) | |
| core_part = re.sub(r"auto ", "", core_part) | |
| core_part = re.sub(r"void ", "", core_part) | |
| core_part = re.sub(r" const", "", core_part) | |
| # To make function signature less verbose, replace templates with <...> | |
| signature = function | |
| while True: | |
| prev = signature | |
| signature = re.sub(r"<[^<>]+>", TEMPLATE_TAG, signature) | |
| if prev == signature: | |
| break | |
| signature = re.sub(TEMPLATE_TAG, "<>", signature) | |
| # Underline the "core part" in the signature | |
| signature = signature.replace(core_part, TerminalEscapeCodes.UNDERLINE + | |
| core_part + TerminalEscapeCodes.ENDC) | |
| return signature | |
| def is_cpp_stacktrace_entry(parts): | |
| return len(parts) >= 7 and parts[3][:3] == "0x0" | |
| def simplify_cpp_stacktrace_entry(parts): | |
| prefix = parts[0] # "[01127.479810][1169][1262][klog]" | |
| level = parts[1] # "INFO:" | |
| index = parts[2] # "#1" | |
| symbol = parts[3] # "0x00005a22a477d585" | |
| function = " ".join(parts[5:-2]) # function signature, can contain spaces | |
| file_path = parts[-2] # file path | |
| function = simplify_cpp_function_signature(function) | |
| file_path = simplify_cpp_file_path(file_path) | |
| file_path = TerminalEscapeCodes.GREEN + file_path + TerminalEscapeCodes.ENDC | |
| return "%s %s %s" % (index, file_path, function) | |
| def main(): | |
| for line in sys.stdin: | |
| line = line.strip() | |
| parts = line.split() | |
| if is_cpp_stacktrace_entry(parts): | |
| print(simplify_cpp_stacktrace_entry(parts)) | |
| else: | |
| # Contributions to handle other stacktrace types very welcome. | |
| print(line) | |
| if __name__ == '__main__': | |
| sys.exit(main()) |