31
31
import concurrent .futures
32
32
import contextlib
33
33
import datetime
34
+ import enum
34
35
import json
35
36
import os
36
37
import platform
45
46
import time
46
47
import uuid
47
48
48
-
49
49
print_lock = threading .RLock ()
50
50
51
51
try :
@@ -1582,9 +1582,12 @@ def synchronous(debugger):
1582
1582
debugger .RunCommandInterpreter (True , False , run_options , 0 , False , True )
1583
1583
1584
1584
1585
- def CreateSymbolicateCrashLogOptions (
1586
- command_name , description , add_interactive_options
1587
- ):
1585
+ class CrashLogLoadingMode (str , enum .Enum ):
1586
+ batch = "batch"
1587
+ interactive = "interactive"
1588
+
1589
+
1590
+ def CreateSymbolicateCrashLogOptions (command_name , description ):
1588
1591
usage = "crashlog [options] <FILE> [FILE ...]"
1589
1592
arg_parser = argparse .ArgumentParser (
1590
1593
description = description ,
@@ -1600,6 +1603,12 @@ def CreateSymbolicateCrashLogOptions(
1600
1603
help = "crash report(s) to symbolicate" ,
1601
1604
)
1602
1605
1606
+ arg_parser .add_argument (
1607
+ "-m" ,
1608
+ "--mode" ,
1609
+ choices = [mode .value for mode in CrashLogLoadingMode ],
1610
+ help = "change how the symbolicated process and threads are displayed to the user (default: interactive)" ,
1611
+ )
1603
1612
arg_parser .add_argument (
1604
1613
"--version" ,
1605
1614
"-V" ,
@@ -1736,36 +1745,35 @@ def CreateSymbolicateCrashLogOptions(
1736
1745
help = argparse .SUPPRESS ,
1737
1746
default = False ,
1738
1747
)
1739
- if add_interactive_options :
1740
- arg_parser .add_argument (
1741
- "-i" ,
1742
- "--interactive" ,
1743
- action = "store_true" ,
1744
- help = "parse a crash log and load it in a ScriptedProcess" ,
1745
- default = False ,
1746
- )
1747
- arg_parser .add_argument (
1748
- "-b" ,
1749
- "--batch" ,
1750
- action = "store_true" ,
1751
- help = "dump symbolicated stackframes without creating a debug session" ,
1752
- default = True ,
1753
- )
1754
- arg_parser .add_argument (
1755
- "--target" ,
1756
- "-t" ,
1757
- dest = "target_path" ,
1758
- help = "the target binary path that should be used for interactive crashlog (optional)" ,
1759
- default = None ,
1760
- )
1761
- arg_parser .add_argument (
1762
- "--skip-status" ,
1763
- "-s" ,
1764
- dest = "skip_status" ,
1765
- action = "store_true" ,
1766
- help = "prevent the interactive crashlog to dump the process status and thread backtrace at launch" ,
1767
- default = False ,
1768
- )
1748
+ arg_parser .add_argument (
1749
+ "--target" ,
1750
+ "-t" ,
1751
+ dest = "target_path" ,
1752
+ help = "the target binary path that should be used for interactive crashlog (optional)" ,
1753
+ default = None ,
1754
+ )
1755
+ arg_parser .add_argument (
1756
+ "--skip-status" ,
1757
+ "-s" ,
1758
+ dest = "skip_status" ,
1759
+ action = "store_true" ,
1760
+ help = "prevent the interactive crashlog to dump the process status and thread backtrace at launch" ,
1761
+ default = False ,
1762
+ )
1763
+ legacy_group = arg_parser .add_mutually_exclusive_group ()
1764
+ legacy_group .add_argument (
1765
+ "-i" ,
1766
+ "--interactive" ,
1767
+ action = "store_true" ,
1768
+ help = argparse .SUPPRESS ,
1769
+ )
1770
+ legacy_group .add_argument (
1771
+ "-b" ,
1772
+ "--batch" ,
1773
+ action = "store_true" ,
1774
+ help = argparse .SUPPRESS ,
1775
+ )
1776
+
1769
1777
return arg_parser
1770
1778
1771
1779
@@ -1778,7 +1786,7 @@ def CrashLogOptionParser():
1778
1786
created that has all of the shared libraries loaded at the load addresses found in the crash log file. This allows
1779
1787
you to explore the program as if it were stopped at the locations described in the crash log and functions can
1780
1788
be disassembled and lookups can be performed using the addresses found in the crash log."""
1781
- return CreateSymbolicateCrashLogOptions ("crashlog" , description , True )
1789
+ return CreateSymbolicateCrashLogOptions ("crashlog" , description )
1782
1790
1783
1791
1784
1792
def SymbolicateCrashLogs (debugger , command_args , result , is_command ):
@@ -1794,8 +1802,35 @@ def SymbolicateCrashLogs(debugger, command_args, result, is_command):
1794
1802
result .SetError (str (e ))
1795
1803
return
1796
1804
1805
+ # To avoid breaking existing users, we should keep supporting legacy flags
1806
+ # even if we don't use them / advertise them anymore.
1807
+ if not options .mode :
1808
+ if options .batch :
1809
+ options .mode = CrashLogLoadingMode .batch
1810
+ else :
1811
+ options .mode = CrashLogLoadingMode .interactive
1812
+
1813
+ if options .mode != CrashLogLoadingMode .interactive and (
1814
+ options .target_path or options .skip_status
1815
+ ):
1816
+ print (
1817
+ "Target path (-t) and skipping process status (-s) options can only used in interactive mode (-m=interactive)."
1818
+ )
1819
+ print ("Aborting symbolication." )
1820
+ arg_parser .print_help ()
1821
+ return
1822
+
1823
+ if options .version :
1824
+ print (debugger .GetVersionString ())
1825
+ return
1826
+
1827
+ if options .debug :
1828
+ print ("command_args = %s" % command_args )
1829
+ print ("options" , options )
1830
+ print ("args" , options .reports )
1831
+
1797
1832
# Interactive mode requires running the crashlog command from inside lldb.
1798
- if options .interactive and not is_command :
1833
+ if options .mode == CrashLogLoadingMode . interactive and not is_command :
1799
1834
lldb_exec = (
1800
1835
subprocess .check_output (["/usr/bin/xcrun" , "-f" , "lldb" ])
1801
1836
.decode ("utf-8" )
@@ -1821,31 +1856,24 @@ def SymbolicateCrashLogs(debugger, command_args, result, is_command):
1821
1856
print (debugger .GetVersionString ())
1822
1857
return
1823
1858
1824
- if options .debug :
1825
- print ("command_args = %s" % command_args )
1826
- print ("options" , options )
1827
- print ("args" , options .reports )
1828
-
1829
1859
if options .debug_delay > 0 :
1830
1860
print ("Waiting %u seconds for debugger to attach..." % options .debug_delay )
1831
1861
time .sleep (options .debug_delay )
1832
1862
error = lldb .SBError ()
1833
1863
1834
1864
def should_run_in_interactive_mode (options , ci ):
1835
- if options .interactive :
1836
- return True
1837
- elif options .batch :
1865
+ if options .mode == CrashLogLoadingMode .batch :
1838
1866
return False
1839
- # elif ci and ci.IsInteractive():
1840
- # return True
1867
+ elif ci and ci .IsInteractive ():
1868
+ return True
1841
1869
else :
1842
- return False
1870
+ return sys . stdout . isatty ()
1843
1871
1844
1872
ci = debugger .GetCommandInterpreter ()
1845
1873
1846
1874
if options .reports :
1847
1875
for crashlog_file in options .reports :
1848
- crashlog_path = os .path .expanduser (crashlog_file )
1876
+ crashlog_path = os .path .normpath ( os . path . expanduser (crashlog_file ) )
1849
1877
if not os .path .exists (crashlog_path ):
1850
1878
raise FileNotFoundError (
1851
1879
"crashlog file %s does not exist" % crashlog_path
0 commit comments