android: stack.py: revert to copying input lines by default

In crrev.com/c/926227 copying of input lines to output was removed, as
it was confusing/slow for interactive use in the terminal. However, some
users appreciate this mode allowing them to pipe adb logcat through the
stack tool.

Inspecting further, the mode that omits irrelevant lines existed: it was
automatically used when FILE was provided (to not be stdin).

Add an option --pass-through (or -p) to control copying the non-trace lines.

Make --pass-through incompatible with reading from a non-stdin FILE because the
idea of the latter is to pre-filter the lines and run them through
multiprocessing.  Pre-filtering, passthrough and post-merging sounds too
complicated right now.

Bug: None
Change-Id: I547435db6d796b02ac7abbad0146fd1588374ff0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3436569
Reviewed-by: Andrew Grieve <agrieve@chromium.org>
Commit-Queue: Egor Pasko <pasko@chromium.org>
Cr-Commit-Position: refs/heads/main@{#967373}
NOKEYCHECK=True
GitOrigin-RevId: a0e06cf4221365fbbab9b1a0316e786b19eb8bbf
diff --git a/development/scripts/stack.py b/development/scripts/stack.py
index 6420406..6e562b4 100755
--- a/development/scripts/stack.py
+++ b/development/scripts/stack.py
@@ -46,8 +46,18 @@
 
 def PrintUsage():
   """Print usage and exit with error."""
+  print("Usage: " + sys.argv[0] + " [options] [FILE]")
   print()
-  print("  usage: " + sys.argv[0] + " [options] [FILE]")
+  print("Find all parts in FILE belonging to stack traces and symbolize")
+  print("them: copy to stdout augmenting with source file names and line")
+  print("numbers.")
+  print()
+  print("Not providing FILE or setting it to '-' implies reading from stdin.")
+  print()
+  print("  -p, --pass-through")
+  print("       Copy all lines from stdin to stdout in addition to")
+  print("       symbolizing relevant lines. This way ADB logcat can")
+  print("       be piped through the tool to symbolize on the fly.")
   print()
   print("  --symbols-dir=path")
   print("       path to the Android OS symbols dir, such as")
@@ -90,13 +100,6 @@
   print("  --verbose")
   print("       enable extra logging, particularly for debugging failed")
   print("       symbolization")
-  print()
-  print("  FILE should contain a stack trace in it somewhere")
-  print("       the tool will find that and re-print it with")
-  print("       source files and line numbers.  If you don't")
-  print("       pass FILE, or if file is -, it reads from")
-  print("       stdin.")
-  print()
   sys.exit(1)
 
 def UnzipSymbols(symbolfile, symdir=None):
@@ -143,14 +146,15 @@
 
 def main(argv, test_symbolizer=None):
   try:
-    options, arguments = getopt.getopt(argv, "", [
-        "more-info", "less-info", "chrome-symbols-dir=", "output-directory=",
-        "apks-directory=", "symbols-dir=", "symbols-zip=", "arch=",
-        "fallback-monochrome", "verbose", "quiet", "help",
+    options, arguments = getopt.getopt(argv, "p", [
+        "pass-through", "more-info", "less-info", "chrome-symbols-dir=",
+        "output-directory=", "apks-directory=", "symbols-dir=", "symbols-zip=",
+        "arch=", "fallback-monochrome", "verbose", "quiet", "help",
     ])
   except getopt.GetoptError:
     PrintUsage()
 
+  pass_through = False
   zip_arg = None
   more_info = False
   fallback_monochrome = False
@@ -160,6 +164,10 @@
   for option, value in options:
     if option == "--help":
       PrintUsage()
+    elif option == "--pass-through":
+      pass_through = True
+    elif option == "-p":
+      pass_through = True
     elif option == "--symbols-dir":
       symbol.SYMBOLS_DIR = os.path.abspath(os.path.expanduser(value))
     elif option == "--symbols-zip":
@@ -202,17 +210,21 @@
   if zip_arg:
     rootdir, symbol.SYMBOLS_DIR = UnzipSymbols(zip_arg)
 
-  if not arguments or arguments[0] == "-":
+  if not arguments or arguments[0] == '-':
     logging.info('Reading native crash info from stdin (symbolization starts '
                  'on the first unrelated line or EOF)')
     with llvm_symbolizer.LLVMSymbolizer() as symbolizer:
       stack_core.StreamingConvertTrace(sys.stdin, {}, more_info,
                                        fallback_monochrome, arch_defined,
-                                       symbolizer, apks_directory)
+                                       symbolizer, apks_directory, pass_through)
   else:
     logging.info('Searching for native crashes in: %s',
                  os.path.realpath(arguments[0]))
-    f = open(arguments[0], "r")
+    if pass_through:
+      logging.error('Processing files in --pass-through mode is not supported')
+      return 1
+
+    f = open(arguments[0], 'r')
 
     lines = f.readlines()
     f.close()
@@ -235,6 +247,8 @@
     logging.info('cleaning up (%s)', cmd)
     os.system(cmd)
 
+  return 0
+
 if __name__ == "__main__":
   sys.exit(main(sys.argv[1:]))
 
diff --git a/development/scripts/stack_core.py b/development/scripts/stack_core.py
index b0937db..0d04f16 100755
--- a/development/scripts/stack_core.py
+++ b/development/scripts/stack_core.py
@@ -143,6 +143,7 @@
       print(' ')
     print(l)
 
+
 def PrintOutput(trace_lines, value_lines, java_lines, more_info):
   if trace_lines:
     PrintTraceLines(trace_lines)
@@ -157,13 +158,15 @@
   if java_lines:
     PrintJavaLines(java_lines)
 
+
 def PrintDivider():
   print()
   print('-----------------------------------------------------\n')
 
 
 def StreamingConvertTrace(_, load_vaddrs, more_info, fallback_monochrome,
-                          arch_defined, llvm_symbolizer, apks_directory):
+                          arch_defined, llvm_symbolizer, apks_directory,
+                          pass_through):
   """Symbolize stacks on the fly as they are read from an input stream."""
 
   if fallback_monochrome:
@@ -188,6 +191,8 @@
   for line in iter(sys.stdin.readline, b''):
     if not line: # EOF
       break
+    if pass_through:
+      sys.stdout.write(line)
     maybe_line, maybe_so_dir = preprocessor([line])
     useful_lines.extend(maybe_line)
     so_dirs.extend(maybe_so_dir)