#!/usr/bin/env python
#
# Copyright (C) 2013 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""stack symbolizes native crash dumps."""

import logging
import re

import symbol

def PrintTraceLines(trace_lines):
  """Print back trace."""
  maxlen = max(map(lambda tl: len(tl[1]), trace_lines))
  print
  print "Stack Trace:"
  print "  RELADDR   " + "FUNCTION".ljust(maxlen) + "  FILE:LINE"
  for tl in trace_lines:
    (addr, symbol_with_offset, location) = tl
    print "  %8s  %s  %s" % (addr, symbol_with_offset.ljust(maxlen), location)
  return


def PrintValueLines(value_lines):
  """Print stack data values."""
  maxlen = max(map(lambda tl: len(tl[2]), value_lines))
  print
  print "Stack Data:"
  print "  ADDR      VALUE     " + "FUNCTION".ljust(maxlen) + "  FILE:LINE"
  for vl in value_lines:
    (addr, value, symbol_with_offset, location) = vl
    print "  %8s  %8s  %s  %s" % (addr, value, symbol_with_offset.ljust(maxlen), location)
  return

UNKNOWN = "<unknown>"
HEAP = "[heap]"
STACK = "[stack]"


def PrintOutput(trace_lines, value_lines, more_info):
  if trace_lines:
    PrintTraceLines(trace_lines)
  if value_lines:
    # TODO(cjhopman): it seems that symbol.SymbolInformation always fails to
    # find information for addresses in value_lines in chrome libraries, and so
    # value_lines have little value to us and merely clutter the output.
    # Since information is sometimes contained in these lines (from system
    # libraries), don't completely disable them.
    if more_info:
      PrintValueLines(value_lines)

def PrintDivider():
  print
  print "-----------------------------------------------------\n"

def ConvertTrace(lines, more_info):
  """Convert strings containing native crash to a stack."""
  process_info_line = re.compile("(pid: [0-9]+, tid: [0-9]+.*)")
  signal_line = re.compile("(signal [0-9]+ \(.*\).*)")
  register_line = re.compile("(([ ]*[0-9a-z]{2} [0-9a-f]{8}){4})")
  thread_line = re.compile("(.*)(\-\-\- ){15}\-\-\-")
  dalvik_jni_thread_line = re.compile("(\".*\" prio=[0-9]+ tid=[0-9]+ NATIVE.*)")
  dalvik_native_thread_line = re.compile("(\".*\" sysTid=[0-9]+ nice=[0-9]+.*)")

  width = "{8}"
  if symbol.ARCH == "arm64" or symbol.ARCH == "x86_64" or symbol.ARCH == "x64":
    width = "{16}"

  # Matches LOG(FATAL) lines, like the following example:
  #   [FATAL:source_file.cc(33)] Check failed: !instances_.empty()
  log_fatal_line = re.compile("(\[FATAL\:.*\].*)$")

  # Note that both trace and value line matching allow for variable amounts of
  # whitespace (e.g. \t). This is because the we want to allow for the stack
  # tool to operate on AndroidFeedback provided system logs. AndroidFeedback
  # strips out double spaces that are found in tombsone files and logcat output.
  #
  # Examples of matched trace lines include lines from tombstone files like:
  #   #00  pc 001cf42e  /data/data/com.my.project/lib/libmyproject.so
  #   #00  pc 001cf42e  /data/data/com.my.project/lib/libmyproject.so (symbol)
  # Or lines from AndroidFeedback crash report system logs like:
  #   03-25 00:51:05.520 I/DEBUG ( 65): #00 pc 001cf42e /data/data/com.my.project/lib/libmyproject.so
  # Please note the spacing differences.
  trace_line = re.compile("(.*)\#(?P<frame>[0-9]+)[ \t]+(..)[ \t]+(0x)?(?P<address>[0-9a-f]{0,16})[ \t]+(?P<lib>[^\r\n \t]*)(?P<symbol_present> \((?P<symbol_name>.*)\))?")  # pylint: disable-msg=C6310

  # Matches lines emitted by src/base/debug/stack_trace_android.cc, like:
  #   #00 0x7324d92d /data/app-lib/org.chromium.native_test-1/libbase.cr.so+0x0006992d
  # This pattern includes the unused named capture groups <symbol_present> and
  # <symbol_name> so that it can interoperate with the |trace_line| regex.
  debug_trace_line = re.compile(
      '(.*)(?P<frame>\#[0-9]+ 0x[0-9a-f]' + width + ') '
      '(?P<lib>[^+]+)\+0x(?P<address>[0-9a-f]' + width + ')'
      '(?P<symbol_present>)(?P<symbol_name>)')

  # Examples of matched value lines include:
  #   bea4170c  8018e4e9  /data/data/com.my.project/lib/libmyproject.so
  #   bea4170c  8018e4e9  /data/data/com.my.project/lib/libmyproject.so (symbol)
  #   03-25 00:51:05.530 I/DEBUG ( 65): bea4170c 8018e4e9 /data/data/com.my.project/lib/libmyproject.so
  # Again, note the spacing differences.
  value_line = re.compile("(.*)([0-9a-f]" + width + ")[ \t]+([0-9a-f]" + width + ")[ \t]+([^\r\n \t]*)( \((.*)\))?")
  # Lines from 'code around' sections of the output will be matched before
  # value lines because otheriwse the 'code around' sections will be confused as
  # value lines.
  #
  # Examples include:
  #   801cf40c ffffc4cc 00b2f2c5 00b2f1c7 00c1e1a8
  #   03-25 00:51:05.530 I/DEBUG ( 65): 801cf40c ffffc4cc 00b2f2c5 00b2f1c7 00c1e1a8
  code_line = re.compile("(.*)[ \t]*[a-f0-9]" + width +
                         "[ \t]*[a-f0-9]" + width +
                         "[ \t]*[a-f0-9]" + width +
                         "[ \t]*[a-f0-9]" + width +
                         "[ \t]*[a-f0-9]" + width +
                         "[ \t]*[ \r\n]")  # pylint: disable-msg=C6310

  trace_lines = []
  value_lines = []
  last_frame = -1

  # It is faster to get symbol information with a single call rather than with
  # separate calls for each line. Since symbol.SymbolInformation caches results,
  # we can extract all the addresses that we will want symbol information for
  # from the log and call symbol.SymbolInformation so that the results are
  # cached in the following lookups.
  code_addresses = {}
  for ln in lines:
    line = unicode(ln, errors='ignore')
    lib, address = None, None

    match = trace_line.match(line) or debug_trace_line.match(line)
    if match:
      address, lib = match.group('address', 'lib')

    match = value_line.match(line)
    if match and not code_line.match(line):
      (_0, _1, address, lib, _2, _3) = match.groups()

    if lib:
      code_addresses.setdefault(lib, set()).add(address)

  for lib in code_addresses:
    symbol.SymbolInformationForSet(
        symbol.TranslateLibPath(lib), code_addresses[lib], more_info)

  for ln in lines:
    # AndroidFeedback adds zero width spaces into its crash reports. These
    # should be removed or the regular expresssions will fail to match.
    line = unicode(ln, errors='ignore')
    process_header = process_info_line.search(line)
    signal_header = signal_line.search(line)
    register_header = register_line.search(line)
    thread_header = thread_line.search(line)
    dalvik_jni_thread_header = dalvik_jni_thread_line.search(line)
    dalvik_native_thread_header = dalvik_native_thread_line.search(line)
    log_fatal_header = log_fatal_line.search(line)
    if (process_header or signal_header or register_header or thread_header or
        dalvik_jni_thread_header or dalvik_native_thread_header or
        log_fatal_header) :
      if trace_lines or value_lines:
        PrintOutput(trace_lines, value_lines, more_info)
        PrintDivider()
        trace_lines = []
        value_lines = []
        last_frame = -1
      if process_header:
        print process_header.group(1)
      if signal_header:
        print signal_header.group(1)
      if register_header:
        print register_header.group(1)
      if thread_header:
        print thread_header.group(1)
      if dalvik_jni_thread_header:
        print dalvik_jni_thread_header.group(1)
      if dalvik_native_thread_header:
        print dalvik_native_thread_header.group(1)
      if log_fatal_header:
        print log_fatal_header.group(1)
      continue

    match = trace_line.match(line) or debug_trace_line.match(line)
    if match:
      frame, code_addr, area, symbol_present, symbol_name = match.group(
          'frame', 'address', 'lib', 'symbol_present', 'symbol_name')
      logging.debug('Found trace line: %s' % line.strip())

      if frame <= last_frame and (trace_lines or value_lines):
        PrintOutput(trace_lines, value_lines, more_info)
        PrintDivider()
        trace_lines = []
        value_lines = []
      last_frame = frame

      if area == UNKNOWN or area == HEAP or area == STACK:
        trace_lines.append((code_addr, "", area))
      else:
        logging.debug('Identified lib: %s' % area)
        # If a calls b which further calls c and c is inlined to b, we want to
        # display "a -> b -> c" in the stack trace instead of just "a -> c"
        info = symbol.SymbolInformation(area, code_addr, more_info)
        logging.debug('symbol information: %s' % info)
        nest_count = len(info) - 1
        for (source_symbol, source_location, object_symbol_with_offset) in info:
          if not source_symbol:
            if symbol_present:
              source_symbol = symbol.CallCppFilt(symbol_name)
            else:
              source_symbol = UNKNOWN
          if not source_location:
            source_location = area
          if nest_count > 0:
            nest_count = nest_count - 1
            trace_lines.append(("v------>", source_symbol, source_location))
          else:
            if not object_symbol_with_offset:
              object_symbol_with_offset = source_symbol
            trace_lines.append((code_addr,
                                object_symbol_with_offset,
                                source_location))
    if code_line.match(line):
      # Code lines should be ignored. If this were exluded the 'code around'
      # sections would trigger value_line matches.
      continue;
    match = value_line.match(line)
    if match:
      (unused_, addr, value, area, symbol_present, symbol_name) = match.groups()
      if area == UNKNOWN or area == HEAP or area == STACK or not area:
        value_lines.append((addr, value, "", area))
      else:
        info = symbol.SymbolInformation(area, value, more_info)
        (source_symbol, source_location, object_symbol_with_offset) = info.pop()
        if not source_symbol:
          if symbol_present:
            source_symbol = symbol.CallCppFilt(symbol_name)
          else:
            source_symbol = UNKNOWN
        if not source_location:
          source_location = area
        if not object_symbol_with_offset:
          object_symbol_with_offset = source_symbol
        value_lines.append((addr,
                            value,
                            object_symbol_with_offset,
                            source_location))

  PrintOutput(trace_lines, value_lines, more_info)
