17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#!/usr/bin/env python
27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#
37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Copyright (C) 2013 The Android Open Source Project
47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#
57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Licensed under the Apache License, Version 2.0 (the "License");
67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# you may not use this file except in compliance with the License.
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# You may obtain a copy of the License at
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#      http://www.apache.org/licenses/LICENSE-2.0
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Unless required by applicable law or agreed to in writing, software
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# distributed under the License is distributed on an "AS IS" BASIS,
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# See the License for the specific language governing permissions and
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# limitations under the License.
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch"""stack symbolizes native crash dumps."""
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport getopt
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport glob
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport os
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport sys
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport stack_core
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport subprocess
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport symbol
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport sys
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochDEFAULT_SYMROOT='/tmp/symbols'
307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochdef PrintUsage():
327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  """Print usage and exit with error."""
337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  # pylint: disable-msg=C6310
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "  usage: " + sys.argv[0] + " [options] [FILE]"
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "  --symbols-dir=path"
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       the path to a symbols dir, such as =/tmp/out/target/product/dream/symbols"
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "  --chrome-symbols-dir=path"
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       the path to a Chrome symbols dir (can be absolute or relative"
427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       to src), such as =out/Debug/lib"
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       If not specified, will look for the newest lib in out/Debug or"
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       out/Release"
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print
467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "  --symbols-zip=path"
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       the path to a symbols zip file, such as =dream-symbols-12345.zip"
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "  --more-info"
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "  --less-info"
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       Change the level of detail in the output."
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       --more-info is slower and more verbose, but more functions will"
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       be fully qualified with namespace/classname and have full"
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       argument information. Also, the 'stack data' section will be"
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       printed."
567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  print "  --arch=arm|arm64|x86_64|x86|mips"
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       the target architecture"
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "  FILE should contain a stack trace in it somewhere"
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       the tool will find that and re-print it with"
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       source files and line numbers.  If you don't"
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       pass FILE, or if file is -, it reads from"
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "       stdin."
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  # pylint: enable-msg=C6310
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  sys.exit(1)
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochdef UnzipSymbols(symbolfile, symdir=None):
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  """Unzips a file to DEFAULT_SYMROOT and returns the unzipped location.
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Args:
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    symbolfile: The .zip file to unzip
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    symdir: Optional temporary directory to use for extraction
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Returns:
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    A tuple containing (the directory into which the zip file was unzipped,
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    the path to the "symbols" directory in the unzipped file).  To clean
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    up, the caller can delete the first element of the tuple.
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  Raises:
827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    SymbolDownloadException: When the unzip fails.
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  """
847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if not symdir:
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    symdir = "%s/%s" % (DEFAULT_SYMROOT, hash(symbolfile))
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if not os.path.exists(symdir):
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    os.makedirs(symdir)
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "extracting %s..." % symbolfile
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  saveddir = os.getcwd()
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  os.chdir(symdir)
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  try:
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    unzipcode = subprocess.call(["unzip", "-qq", "-o", symbolfile])
947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if unzipcode > 0:
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      os.remove(symbolfile)
967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      raise SymbolDownloadException("failed to extract symbol files (%s)."
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                    % symbolfile)
987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  finally:
997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    os.chdir(saveddir)
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  android_symbols = glob.glob("%s/out/target/product/*/symbols" % symdir)
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if android_symbols:
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return (symdir, android_symbols[0])
1047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  else:
1057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    # This is a zip of Chrome symbols, so symbol.CHROME_SYMBOLS_DIR needs to be
1067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    # updated to point here.
1077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    symbol.CHROME_SYMBOLS_DIR = symdir
1087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return (symdir, symdir)
1097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochdef main():
1127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  try:
1137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    options, arguments = getopt.getopt(sys.argv[1:], "",
1147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                       ["more-info",
1157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                        "less-info",
1167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                        "chrome-symbols-dir=",
1177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                        "symbols-dir=",
1187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                        "symbols-zip=",
1197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                        "arch=",
1207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                        "help"])
1217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  except getopt.GetoptError, unused_error:
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    PrintUsage()
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  zip_arg = None
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  more_info = False
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for option, value in options:
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if option == "--help":
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      PrintUsage()
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    elif option == "--symbols-dir":
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      symbol.SYMBOLS_DIR = os.path.expanduser(value)
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    elif option == "--symbols-zip":
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      zip_arg = os.path.expanduser(value)
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    elif option == "--arch":
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      symbol.ARCH = value
1357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    elif option == "--chrome-symbols-dir":
1367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      symbol.CHROME_SYMBOLS_DIR = os.path.join(symbol.CHROME_SYMBOLS_DIR, value)
1377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    elif option == "--more-info":
1387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      more_info = True
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    elif option == "--less-info":
1407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      more_info = False
1417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if len(arguments) > 1:
1437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    PrintUsage()
1447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if not arguments or arguments[0] == "-":
1467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    print "Reading native crash info from stdin"
1477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    f = sys.stdin
1487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  else:
1497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    print "Searching for native crashes in %s" % arguments[0]
1507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    f = open(arguments[0], "r")
1517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  lines = f.readlines()
1537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  f.close()
1547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  rootdir = None
1567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if zip_arg:
1577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    rootdir, symbol.SYMBOLS_DIR = UnzipSymbols(zip_arg)
1587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "Reading Android symbols from", symbol.SYMBOLS_DIR
1607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  print "Reading Chrome symbols from", symbol.CHROME_SYMBOLS_DIR
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  stack_core.ConvertTrace(lines, more_info)
1627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if rootdir:
1647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    # be a good citizen and clean up...os.rmdir and os.removedirs() don't work
1657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    cmd = "rm -rf \"%s\"" % rootdir
1667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    print "\ncleaning up (%s)" % cmd
1677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    os.system(cmd)
1687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochif __name__ == "__main__":
1707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  main()
1717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# vi: ts=2 sw=2
173