#!/usr/bin/env python
#
# 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.

from __future__ import print_function

import argparse
import os
import re
import sys
import tempfile

if __name__ == '__main__':
  sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
from pylib.constants import host_paths

if host_paths.DEVIL_PATH not in sys.path:
  sys.path.append(host_paths.DEVIL_PATH)
from devil.utils import cmd_helper


_MICRODUMP_BEGIN = re.compile(
    '.*google-breakpad: -----BEGIN BREAKPAD MICRODUMP-----')
_MICRODUMP_END = re.compile(
    '.*google-breakpad: -----END BREAKPAD MICRODUMP-----')

""" Example Microdump
<timestamp>  6270  6131 F google-breakpad: -----BEGIN BREAKPAD MICRODUMP-----
<timestamp>  6270  6131 F google-breakpad: V Chrome_Android:54.0.2790.0
...
<timestamp>  6270  6131 F google-breakpad: -----END BREAKPAD MICRODUMP-----

"""


def GetMicroDumps(dump_path):
  """Returns all microdumps found in given log file

  Args:
    dump_path: Path to the log file.

  Returns:
    List of all microdumps as lists of lines.
  """
  with open(dump_path, 'r') as d:
    data = d.read()
  all_dumps = []
  current_dump = None
  for line in data.splitlines():
    if current_dump is not None:
      if _MICRODUMP_END.match(line):
        current_dump.append(line)
        all_dumps.append(current_dump)
        current_dump = None
      else:
        current_dump.append(line)
    elif _MICRODUMP_BEGIN.match(line):
      current_dump = []
      current_dump.append(line)
  return all_dumps


def SymbolizeMicroDump(stackwalker_binary_path, dump, symbols_path):
  """Runs stackwalker on microdump.

  Runs the stackwalker binary at stackwalker_binary_path on a given microdump
  using the symbols at symbols_path.

  Args:
    stackwalker_binary_path: Path to the stackwalker binary.
    dump: The microdump to run the stackwalker on.
    symbols_path: Path the the symbols file to use.

  Returns:
    Output from stackwalker tool.
  """
  with tempfile.NamedTemporaryFile() as tf:
    for l in dump:
      tf.write('%s\n' % l)
    cmd = [stackwalker_binary_path, tf.name, symbols_path]
    return cmd_helper.GetCmdOutput(cmd)


def AddArguments(parser):
  parser.add_argument('--stackwalker-binary-path', required=True,
                      help='Path to stackwalker binary.')
  parser.add_argument('--stack-trace-path', required=True,
                      help='Path to stacktrace containing microdump.')
  parser.add_argument('--symbols-path', required=True,
                      help='Path to symbols file.')
  parser.add_argument('--output-file',
                      help='Path to dump stacktrace output to')


def _PrintAndLog(line, fp):
  if fp:
    fp.write('%s\n' % line)
  print(line)


def main():
  parser = argparse.ArgumentParser()
  AddArguments(parser)
  args = parser.parse_args()

  micro_dumps = GetMicroDumps(args.stack_trace_path)
  if not micro_dumps:
    print('No microdump found. Exiting.')
    return 0

  symbolized_dumps = []
  for micro_dump in micro_dumps:
    symbolized_dumps.append(SymbolizeMicroDump(
        args.stackwalker_binary_path, micro_dump, args.symbols_path))

  try:
    fp = open(args.output_file, 'w') if args.output_file else None
    _PrintAndLog('%d microdumps found.' % len(micro_dumps), fp)
    _PrintAndLog('---------- Start output from stackwalker ----------', fp)
    for index, symbolized_dump in list(enumerate(symbolized_dumps)):
      _PrintAndLog(
          '------------------ Start dump %d ------------------' % index, fp)
      _PrintAndLog(symbolized_dump, fp)
      _PrintAndLog(
          '------------------- End dump %d -------------------' % index, fp)
    _PrintAndLog('----------- End output from stackwalker -----------', fp)
  except Exception:
    if fp:
      fp.close()
    raise
  return 0


if __name__ == '__main__':
  sys.exit(main())
